summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rwxr-xr-xbin/syncqt.pl7
-rw-r--r--config.tests/common/aesni/aesni.cpp49
-rw-r--r--config.tests/common/aesni/aesni.pro3
-rw-r--r--config.tests/common/shani/shani.cpp50
-rw-r--r--config.tests/common/shani/shani.pro3
-rw-r--r--config.tests/qpa/vulkan/vulkan.cpp58
-rw-r--r--config.tests/qpa/vulkan/vulkan.pro1
-rw-r--r--configure.json26
-rw-r--r--doc/global/config.qdocconf4
-rw-r--r--examples/examples.pro6
-rw-r--r--examples/opengl/qopenglwidget/glwidget.cpp6
-rw-r--r--examples/opengl/qopenglwidget/main.cpp2
-rw-r--r--examples/touch/pinchzoom/mouse.cpp10
-rw-r--r--examples/vulkan/doc/images/hellovulkantexture.pngbin0 -> 10259 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkantriangle.pngbin0 -> 30952 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkanwidget.pngbin0 -> 25256 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkanwindow.pngbin0 -> 2736 bytes
-rw-r--r--examples/vulkan/doc/src/hellovulkantexture.qdoc41
-rw-r--r--examples/vulkan/doc/src/hellovulkantriangle.qdoc49
-rw-r--r--examples/vulkan/doc/src/hellovulkanwidget.qdoc49
-rw-r--r--examples/vulkan/doc/src/hellovulkanwindow.qdoc101
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.cpp828
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.h108
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.pro7
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.qrc7
-rw-r--r--examples/vulkan/hellovulkantexture/main.cpp91
-rw-r--r--examples/vulkan/hellovulkantexture/qt256.pngbin0 -> 6208 bytes
-rw-r--r--examples/vulkan/hellovulkantexture/texture.frag12
-rw-r--r--examples/vulkan/hellovulkantexture/texture.vert18
-rw-r--r--examples/vulkan/hellovulkantexture/texture_frag.spvbin0 -> 556 bytes
-rw-r--r--examples/vulkan/hellovulkantexture/texture_vert.spvbin0 -> 968 bytes
-rw-r--r--examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro12
-rw-r--r--examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc6
-rw-r--r--examples/vulkan/hellovulkantriangle/main.cpp100
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp182
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.h98
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro16
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc6
-rw-r--r--examples/vulkan/hellovulkanwidget/main.cpp93
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp128
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.h77
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro6
-rw-r--r--examples/vulkan/hellovulkanwindow/main.cpp (renamed from src/corelib/doc/snippets/signalmapper/filereader.cpp)90
-rw-r--r--examples/vulkan/shared/color.frag10
-rw-r--r--examples/vulkan/shared/color.vert18
-rw-r--r--examples/vulkan/shared/color_frag.spvbin0 -> 496 bytes
-rw-r--r--examples/vulkan/shared/color_vert.spvbin0 -> 960 bytes
-rw-r--r--examples/vulkan/shared/trianglerenderer.cpp513
-rw-r--r--examples/vulkan/shared/trianglerenderer.h85
-rw-r--r--examples/vulkan/vulkan.pro7
-rw-r--r--examples/widgets/graphicsview/collidingmice/mouse.cpp10
-rw-r--r--examples/widgets/graphicsview/diagramscene/arrow.cpp6
-rw-r--r--examples/widgets/graphicsview/elasticnodes/edge.cpp7
-rw-r--r--examples/widgets/itemviews/chart/pieview.cpp6
-rw-r--r--examples/widgets/mainwindows/mainwindow/mainwindow.cpp1
-rw-r--r--examples/xml/dombookmarks/mainwindow.cpp44
-rw-r--r--examples/xml/dombookmarks/mainwindow.h9
-rw-r--r--examples/xml/dombookmarks/xbeltree.cpp74
-rw-r--r--examples/xml/dombookmarks/xbeltree.h11
-rw-r--r--examples/xml/saxbookmarks/mainwindow.cpp67
-rw-r--r--examples/xml/saxbookmarks/mainwindow.h13
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.cpp18
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.h6
-rw-r--r--examples/xml/saxbookmarks/xbelhandler.cpp28
-rw-r--r--examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc2
-rw-r--r--examples/xml/streambookmarks/mainwindow.cpp75
-rw-r--r--examples/xml/streambookmarks/mainwindow.h13
-rw-r--r--examples/xml/streambookmarks/xbelreader.cpp36
-rw-r--r--examples/xml/streambookmarks/xbelreader.h4
-rw-r--r--examples/xml/streambookmarks/xbelwriter.cpp29
-rw-r--r--examples/xml/streambookmarks/xbelwriter.h6
-rw-r--r--mkspecs/common/gcc-base.conf2
-rw-r--r--mkspecs/common/linux.conf1
-rw-r--r--mkspecs/common/msvc-desktop.conf3
-rw-r--r--mkspecs/common/qcc-base.conf2
-rw-r--r--mkspecs/common/windows-vulkan.conf5
-rw-r--r--mkspecs/common/winrt_winphone/qmake.conf2
-rw-r--r--mkspecs/features/qt_module_headers.prf9
-rw-r--r--mkspecs/features/simd.prf2
-rw-r--r--mkspecs/linux-icc-k1om/qmake.conf21
-rw-r--r--mkspecs/linux-icc-k1om/qplatformdefs.h40
-rw-r--r--mkspecs/linux-icc/qmake.conf2
-rw-r--r--mkspecs/macx-icc/qmake.conf2
-rw-r--r--mkspecs/win32-g++/qmake.conf3
-rw-r--r--mkspecs/win32-icc-k1om/qmake.conf15
-rw-r--r--mkspecs/win32-icc-k1om/qplatformdefs.h40
-rw-r--r--mkspecs/win32-icc/qmake.conf3
-rw-r--r--qmake/Makefile.unix349
-rw-r--r--qmake/Makefile.win321
-rw-r--r--qmake/doc/src/qmake-manual.qdoc14
-rw-r--r--qmake/library/qmakebuiltins.cpp17
-rw-r--r--qmake/qmake.pri5
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java33
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java4
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp16
-rw-r--r--src/corelib/doc/src/objectmodel/signalsandslots.qdoc22
-rw-r--r--src/corelib/global/qglobal.cpp7
-rw-r--r--src/corelib/global/qglobal.h20
-rw-r--r--src/corelib/global/qlogging.cpp28
-rw-r--r--src/corelib/global/qnamespace.h1
-rw-r--r--src/corelib/global/qnamespace.qdoc5
-rw-r--r--src/corelib/global/qtypeinfo.h10
-rw-r--r--src/corelib/io/qabstractfileengine.cpp13
-rw-r--r--src/corelib/io/qabstractfileengine_p.h1
-rw-r--r--src/corelib/io/qdatastream.cpp1
-rw-r--r--src/corelib/io/qdatastream.h5
-rw-r--r--src/corelib/io/qdebug.cpp15
-rw-r--r--src/corelib/io/qdebug.h3
-rw-r--r--src/corelib/io/qfile.cpp37
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp18
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp52
-rw-r--r--src/corelib/io/qfsfileengine.cpp4
-rw-r--r--src/corelib/io/qfsfileengine_p.h1
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp17
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp9
-rw-r--r--src/corelib/io/qsettings.cpp2
-rw-r--r--src/corelib/io/qsettings_p.h2
-rw-r--r--src/corelib/io/qtemporaryfile_p.h2
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp376
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h4
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp2
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h2
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm4
-rw-r--r--src/corelib/kernel/qcore_unix_p.h2
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h1
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp6
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h2
-rw-r--r--src/corelib/kernel/qmetatype.h47
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/kernel/qobject_p.h1
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp8
-rw-r--r--src/corelib/kernel/qsignalmapper.h6
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp8
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h2
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp1
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp8
-rw-r--r--src/corelib/thread/qresultstore.h2
-rw-r--r--src/corelib/thread/qsemaphore.cpp153
-rw-r--r--src/corelib/thread/qsemaphore.h39
-rw-r--r--src/corelib/tools/qchar.cpp18
-rw-r--r--src/corelib/tools/qchar.h7
-rw-r--r--src/corelib/tools/qlocale.cpp41
-rw-r--r--src/corelib/tools/qlocale_p.h27
-rw-r--r--src/corelib/tools/qringbuffer_p.h2
-rw-r--r--src/corelib/tools/qsimd_p.h2
-rw-r--r--src/corelib/tools/qstring.cpp225
-rw-r--r--src/corelib/tools/qstring.h47
-rw-r--r--src/corelib/tools/qstringlist.cpp34
-rw-r--r--src/corelib/tools/qstringlist.h7
-rw-r--r--src/corelib/tools/qstringview.cpp533
-rw-r--r--src/corelib/tools/qstringview.h226
-rw-r--r--src/corelib/tools/qtimezoneprivate_icu.cpp5
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp2
-rw-r--r--src/corelib/tools/qvarlengtharray.h4
-rw-r--r--src/corelib/tools/tools.pri3
-rw-r--r--src/gui/configure.json15
-rw-r--r--src/gui/gui.pro1
-rw-r--r--src/gui/image/qiconloader.cpp14
-rw-r--r--src/gui/image/qiconloader_p.h3
-rw-r--r--src/gui/image/qimagereader.cpp11
-rw-r--r--src/gui/image/qimagewriter.cpp10
-rw-r--r--src/gui/image/qimagewriter.h3
-rw-r--r--src/gui/image/qpixmap.cpp71
-rw-r--r--src/gui/image/qplatformpixmap.cpp76
-rw-r--r--src/gui/image/qplatformpixmap.h3
-rw-r--r--src/gui/kernel/qcursor.cpp48
-rw-r--r--src/gui/kernel/qcursor.h4
-rw-r--r--src/gui/kernel/qdnd.cpp5
-rw-r--r--src/gui/kernel/qdnd_p.h1
-rw-r--r--src/gui/kernel/qkeysequence.cpp8
-rw-r--r--src/gui/kernel/qplatformdrag.h1
-rw-r--r--src/gui/kernel/qplatformintegration.cpp31
-rw-r--r--src/gui/kernel/qplatformintegration.h10
-rw-r--r--src/gui/kernel/qplatformtheme.cpp4
-rw-r--r--src/gui/kernel/qplatformtheme.h3
-rw-r--r--src/gui/kernel/qplatformwindow.cpp2
-rw-r--r--src/gui/kernel/qplatformwindow.h2
-rw-r--r--src/gui/kernel/qsimpledrag.cpp7
-rw-r--r--src/gui/kernel/qsimpledrag_p.h1
-rw-r--r--src/gui/kernel/qstylehints.cpp11
-rw-r--r--src/gui/kernel/qstylehints.h1
-rw-r--r--src/gui/kernel/qsurface.cpp2
-rw-r--r--src/gui/kernel/qsurface.h1
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp69
-rw-r--r--src/gui/kernel/qsurfaceformat.h9
-rw-r--r--src/gui/kernel/qwindow.cpp146
-rw-r--r--src/gui/kernel/qwindow.h10
-rw-r--r--src/gui/kernel/qwindow_p.h11
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp4
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h2
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h6
-rw-r--r--src/gui/painting/qdrawhelper.cpp645
-rw-r--r--src/gui/painting/qgrayraster.c809
-rw-r--r--src/gui/painting/qpaintengine.cpp4
-rw-r--r--src/gui/painting/qpaintengine_p.h25
-rw-r--r--src/gui/painting/qpdf.cpp17
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp34
-rw-r--r--src/gui/painting/qplatformbackingstore.h3
-rw-r--r--src/gui/text/qdistancefield.cpp10
-rw-r--r--src/gui/text/qfontsubset.cpp8
-rw-r--r--src/gui/vulkan/KHRONOS_LICENSE.txt20
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.cpp88
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.h (renamed from src/corelib/tools/qpodlist_p.h)88
-rw-r--r--src/gui/vulkan/qt_attribution.json17
-rw-r--r--src/gui/vulkan/qvulkanfunctions.cpp177
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp840
-rw-r--r--src/gui/vulkan/qvulkaninstance.h163
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp2713
-rw-r--r--src/gui/vulkan/qvulkanwindow.h161
-rw-r--r--src/gui/vulkan/qvulkanwindow_p.h188
-rw-r--r--src/gui/vulkan/vk.xml5269
-rw-r--r--src/gui/vulkan/vulkan.pri50
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp3
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp4
-rw-r--r--src/network/ssl/qsslsocket.cpp7
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp130
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp44
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp10
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h5
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow.cpp2
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow_p.h4
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp48
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience_p.h15
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp2
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp1
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h1
-rw-r--r--src/platformsupport/platformsupport.pro3
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp357
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h106
-rw-r--r--src/platformsupport/vkconvenience/vkconvenience.pro16
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux.cpp2
-rw-r--r--src/plugins/platforms/android/android.pro9
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp37
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h7
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp66
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkaninstance.h63
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp210
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.h91
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp4
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm4
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp22
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h5
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.cpp21
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.h4
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm4
-rw-r--r--src/plugins/platforms/ios/qioswindow.h2
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm28
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp10
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h2
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.h1
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.cpp23
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp27
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h4
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp190
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h24
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp140
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h28
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h106
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp26
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp69
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp72
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h17
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp136
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h76
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp273
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h20
-rw-r--r--src/plugins/platforms/windows/windows.pri6
-rw-r--r--src/plugins/platforms/windows/windows.pro2
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp21
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h11
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp3
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp13
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp17
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp102
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp86
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp373
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h59
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp44
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp131
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp30
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp26
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp58
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp52
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp532
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h57
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp38
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.cpp156
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.h79
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkanwindow.cpp88
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkanwindow.h65
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp565
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h8
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp58
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro12
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp1
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp69
-rw-r--r--src/sql/doc/snippets/code/doc_src_sql-driver.cpp5
-rw-r--r--src/sql/doc/src/sql-driver.qdoc16
-rw-r--r--src/sql/kernel/qsqldatabase.cpp1
-rw-r--r--src/src.pro8
-rw-r--r--src/tools/moc/main.cpp4
-rw-r--r--src/tools/qvkgen/qvkgen.cpp530
-rw-r--r--src/tools/qvkgen/qvkgen.pro5
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp2
-rw-r--r--src/widgets/doc/snippets/macmainwindow.mm2
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc6
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp3
-rw-r--r--src/widgets/kernel/qaction.cpp45
-rw-r--r--src/widgets/kernel/qaction.h3
-rw-r--r--src/widgets/kernel/qaction_p.h3
-rw-r--r--src/widgets/kernel/qboxlayout.cpp28
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp84
-rw-r--r--src/widgets/kernel/qopenglwidget.h3
-rw-r--r--src/widgets/kernel/qwidget.cpp47
-rw-r--r--src/widgets/kernel/qwidget_p.h10
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp4
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp28
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp13
-rw-r--r--src/widgets/styles/qcommonstyle.cpp3
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm62
-rw-r--r--src/widgets/styles/qmacstyle_mac_p.h6
-rw-r--r--src/widgets/styles/qstyle.cpp5
-rw-r--r--src/widgets/styles/qstyle.h1
-rw-r--r--src/widgets/styles/qstylehelper.cpp29
-rw-r--r--src/widgets/styles/qstylehelper_p.h5
-rw-r--r--src/widgets/styles/qstyleoption.cpp12
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp2
-rw-r--r--src/widgets/widgets/qcombobox.cpp5
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp99
-rw-r--r--src/widgets/widgets/qdockarealayout_p.h2
-rw-r--r--src/widgets/widgets/qdockwidget.cpp5
-rw-r--r--src/widgets/widgets/qlineedit.cpp5
-rw-r--r--src/widgets/widgets/qmainwindow.cpp86
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp182
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h36
-rw-r--r--src/widgets/widgets/qmdiarea.cpp3
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp53
-rw-r--r--src/widgets/widgets/qmenu.cpp5
-rw-r--r--src/widgets/widgets/qpushbutton.cpp4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp5
-rw-r--r--sync.profile7
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp41
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp17
-rw-r--r--tests/auto/corelib/itemmodels/itemmodels.pro1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp141
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro8
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp727
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp24
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp2
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp50
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp34
-rw-r--r--tests/auto/corelib/tools/qchar/tst_qchar.cpp29
-rw-r--r--tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp17
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp4
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp46
-rw-r--r--tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp211
-rw-r--r--tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp9
-rw-r--r--tests/auto/corelib/tools/qstringview/.gitignore1
-rw-r--r--tests/auto/corelib/tools/qstringview/qstringview.pro6
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp446
-rw-r--r--tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp8
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp2
-rw-r--r--tests/auto/corelib/tools/tools.pro1
-rw-r--r--tests/auto/gui/gui.pro3
-rw-r--r--tests/auto/gui/image/qicon/tst_qicon.cpp10
-rw-r--r--tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp16
-rw-r--r--tests/auto/gui/kernel/kernel.pro1
-rw-r--r--tests/auto/gui/kernel/qcursor/qcursor.pro6
-rw-r--r--tests/auto/gui/kernel/qcursor/tst_qcursor.cpp123
-rw-r--r--tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp12
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp45
-rw-r--r--tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp103
-rw-r--r--tests/auto/gui/qvulkan/qvulkan.pro9
-rw-r--r--tests/auto/gui/qvulkan/tst_qvulkan.cpp435
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp46
-rw-r--r--tests/auto/other/macnativeevents/macnativeevents.pro3
-rw-r--r--tests/auto/other/macnativeevents/qnativeevents.cpp4
-rw-r--r--tests/auto/other/macnativeevents/qnativeevents.h4
-rw-r--r--tests/auto/other/macnativeevents/qnativeevents_mac.cpp42
-rw-r--r--tests/auto/other/macnativeevents/tst_macnativeevents.cpp6
-rw-r--r--tests/auto/other/modeltest/dynamictreemodel.cpp301
-rw-r--r--tests/auto/other/modeltest/dynamictreemodel.h192
-rw-r--r--tests/auto/other/modeltest/modeltest.cpp350
-rw-r--r--tests/auto/other/modeltest/modeltest.h61
-rw-r--r--tests/auto/other/modeltest/tst_modeltest.cpp39
-rw-r--r--tests/auto/other/qaccessibilitymac/qaccessibilitymac.pro1
-rw-r--r--tests/auto/shared/platformclipboard.h10
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp34
-rw-r--r--tests/auto/tools/qmakelib/evaltest.cpp38
-rw-r--r--tests/auto/tools/uic/tst_uic.cpp5
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp6
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp54
-rw-r--r--tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp4
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp2
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp39
-rw-r--r--tests/manual/manual.pro2
-rw-r--r--tests/manual/qvulkaninstance/main.cpp713
-rw-r--r--tests/manual/qvulkaninstance/qvulkaninstance.pro6
426 files changed, 24680 insertions, 4989 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 6d42bbdd34..5153f8139f 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -4,4 +4,4 @@ CONFIG += warning_clean
QT_SOURCE_TREE = $$PWD
QT_BUILD_TREE = $$shadowed($$PWD)
-MODULE_VERSION = 5.9.0
+MODULE_VERSION = 5.10.0
diff --git a/bin/syncqt.pl b/bin/syncqt.pl
index 372aa2b331..d62ffcbc37 100755
--- a/bin/syncqt.pl
+++ b/bin/syncqt.pl
@@ -1004,13 +1004,16 @@ foreach my $lib (@modules_to_sync) {
@headers = grep(!/^qt[a-z0-9]+-config(_p)?\.h$/, @headers);
if (defined $inject_headers{$subdir}) {
foreach my $if (@{$inject_headers{$subdir}}) {
- @headers = grep(!/^\Q$if\E$/, @headers); #in case we configure'd previously
+ my $cif = $if;
+ $cif =~ s/^\^//;
+ @headers = grep(!/^\Q$cif\E$/, @headers); #in case we configure'd previously
push @headers, "*".$if;
}
}
my $header_dirname = "";
foreach my $header (@headers) {
my $shadow = ($header =~ s/^\*//);
+ my $no_stamp = $shadow && ($header =~ s/^\^//);
$header = 0 if ($header =~ /^ui_.*\.h$/);
foreach (@ignore_headers) {
$header = 0 if($header eq $_);
@@ -1106,7 +1109,7 @@ foreach my $lib (@modules_to_sync) {
$pri_install_pfiles.= "$pri_install_iheader ";;
}
$pri_injections .= fixPaths($iheader, "$out_basedir/include/$lib")
- .":".fixPaths($oheader, "$out_basedir/include/$lib")
+ .":".($no_stamp ? "^" : "").fixPaths($oheader, "$out_basedir/include/$lib")
.$injection." " if ($shadow);
}
diff --git a/config.tests/common/aesni/aesni.cpp b/config.tests/common/aesni/aesni.cpp
new file mode 100644
index 0000000000..a177183c72
--- /dev/null
+++ b/config.tests/common/aesni/aesni.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 <wmmintrin.h>
+
+int main(int, char**)
+{
+ __m128i a = _mm_setzero_si128();
+ __m128i b = _mm_aesenc_si128(a, a);
+ __m128i c = _mm_aesdec_si128(a, b);
+ (void)c;
+ return 0;
+}
diff --git a/config.tests/common/aesni/aesni.pro b/config.tests/common/aesni/aesni.pro
new file mode 100644
index 0000000000..49cb132ef7
--- /dev/null
+++ b/config.tests/common/aesni/aesni.pro
@@ -0,0 +1,3 @@
+SOURCES = aesni.cpp
+!defined(QMAKE_CFLAGS_AESNI, "var"): error("This compiler does not support AES New Instructions")
+else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AESNI
diff --git a/config.tests/common/shani/shani.cpp b/config.tests/common/shani/shani.cpp
new file mode 100644
index 0000000000..0fe6e87dd8
--- /dev/null
+++ b/config.tests/common/shani/shani.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 <immintrin.h>
+
+int main(int, char**)
+{
+ __m128i a = _mm_setzero_si128();
+ __m128i b = _mm_sha1rnds4_epu32(a, a, 0);
+ __m128i c = _mm_sha1msg1_epu32(a, b);
+ __m128i d = _mm_sha256msg2_epu32(b, c);
+ (void)d;
+ return 0;
+}
diff --git a/config.tests/common/shani/shani.pro b/config.tests/common/shani/shani.pro
new file mode 100644
index 0000000000..278f49ef90
--- /dev/null
+++ b/config.tests/common/shani/shani.pro
@@ -0,0 +1,3 @@
+SOURCES = shani.cpp
+!defined(QMAKE_CFLAGS_SHANI, "var"): error("This compiler does not support Secure Hash Algorithm extensions")
+else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SHANI
diff --git a/config.tests/qpa/vulkan/vulkan.cpp b/config.tests/qpa/vulkan/vulkan.cpp
new file mode 100644
index 0000000000..22f5edf9f2
--- /dev/null
+++ b/config.tests/qpa/vulkan/vulkan.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is a header-only test. Qt does not rely on linking to a Vulkan library directly.
+
+#include <vulkan/vulkan.h>
+
+// The pData parameter has changed from uint32_t* to void* at some point.
+// Ensure the headers have the updated one to prevent compile errors later on.
+PFN_vkCmdUpdateBuffer cmdUpdBuf;
+void testUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)
+{
+ cmdUpdBuf(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+}
+
+int main(int, char **)
+{
+ VkInstanceCreateInfo info;
+ testUpdateBuffer(0, 0, 0, 0, 0);
+
+ return 0;
+}
diff --git a/config.tests/qpa/vulkan/vulkan.pro b/config.tests/qpa/vulkan/vulkan.pro
new file mode 100644
index 0000000000..5f05bc49aa
--- /dev/null
+++ b/config.tests/qpa/vulkan/vulkan.pro
@@ -0,0 +1 @@
+SOURCES = vulkan.cpp
diff --git a/configure.json b/configure.json
index c5be88856d..69019afa80 100644
--- a/configure.json
+++ b/configure.json
@@ -315,11 +315,21 @@
"type": "compile",
"test": "common/sse4_2"
},
+ "aesni": {
+ "label": "AES new instructions",
+ "type": "compile",
+ "test": "common/aesni"
+ },
"f16c": {
"label": "F16C instructions",
"type": "compile",
"test": "common/f16c"
},
+ "shani": {
+ "label": "SHA new instructions",
+ "type": "compile",
+ "test": "common/shani"
+ },
"avx": {
"label": "AVX instructions",
"type": "compile",
@@ -869,6 +879,22 @@
{ "type": "define", "name": "QT_COMPILER_SUPPORTS_AVX512VBMI", "value": 1 }
]
},
+ "aesni": {
+ "label": "aesni",
+ "condition": "features.sse2 && tests.aesni",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_AES", "value": 1 }
+ ]
+ },
+ "shani": {
+ "label": "shani",
+ "condition": "features.sse2 && tests.shani",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_SHA", "value": 1 }
+ ]
+ },
"mips_dsp": {
"label": "DSP",
"condition": "arch.mips && tests.mips_dsp",
diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf
index 0c22d70529..a18396876d 100644
--- a/doc/global/config.qdocconf
+++ b/doc/global/config.qdocconf
@@ -13,3 +13,7 @@ navigation.homepage = "Qt $QT_VER"
sourcedirs += includes $$BUILDDIR
url = http://doc.qt.io/qt-5
+
+# Uncomment the following two lines to generate documentation marked as \internal
+# alias.internal = disable
+# macro.internal.HTML = "<span style="color:red">[internal]</span>"
diff --git a/examples/examples.pro b/examples/examples.pro
index a3851c6d81..4ec5ca60e2 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -14,7 +14,11 @@ qtHaveModule(concurrent): SUBDIRS += qtconcurrent
qtHaveModule(sql): SUBDIRS += sql
qtHaveModule(widgets): SUBDIRS += widgets
qtHaveModule(xml): SUBDIRS += xml
-qtHaveModule(gui): SUBDIRS += gui opengl
+qtHaveModule(gui) {
+ SUBDIRS += gui
+ qtConfig(opengl): SUBDIRS += opengl
+ qtConfig(vulkan): SUBDIRS += vulkan
+}
aggregate.files = aggregate/examples.pro
aggregate.path = $$[QT_INSTALL_EXAMPLES]
diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp
index 21d922d713..bb7c952a26 100644
--- a/examples/opengl/qopenglwidget/glwidget.cpp
+++ b/examples/opengl/qopenglwidget/glwidget.cpp
@@ -61,6 +61,10 @@
const int bubbleNum = 8;
+#ifndef GL_SRGB8_ALPHA8
+#define GL_SRGB8_ALPHA8 0x8C43
+#endif
+
GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
: m_mainWindow(mw),
m_showBubbles(true),
@@ -75,6 +79,8 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
m_background(background)
{
setMinimumSize(300, 250);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ setTextureFormat(GL_SRGB8_ALPHA8);
}
GLWidget::~GLWidget()
diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp
index d7aa791142..f9b5731b8f 100644
--- a/examples/opengl/qopenglwidget/main.cpp
+++ b/examples/opengl/qopenglwidget/main.cpp
@@ -61,6 +61,8 @@ int main( int argc, char ** argv )
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);
diff --git a/examples/touch/pinchzoom/mouse.cpp b/examples/touch/pinchzoom/mouse.cpp
index f063e96654..3b8e6b5690 100644
--- a/examples/touch/pinchzoom/mouse.cpp
+++ b/examples/touch/pinchzoom/mouse.cpp
@@ -54,7 +54,7 @@
#include <QPainter>
#include <QStyleOption>
-#include <math.h>
+#include <cmath>
static const double Pi = 3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;
@@ -139,9 +139,7 @@ void Mouse::timerEvent(QTimerEvent *)
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
- qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
- if (lineToCenter.dy() < 0)
- angleToCenter = TwoPi - angleToCenter;
+ qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
@@ -170,9 +168,7 @@ void Mouse::timerEvent(QTimerEvent *)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
- qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
- if (lineToMouse.dy() < 0)
- angleToMouse = TwoPi - angleToMouse;
+ qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
diff --git a/examples/vulkan/doc/images/hellovulkantexture.png b/examples/vulkan/doc/images/hellovulkantexture.png
new file mode 100644
index 0000000000..0cb47a70be
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkantexture.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkantriangle.png b/examples/vulkan/doc/images/hellovulkantriangle.png
new file mode 100644
index 0000000000..f88b27a873
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkantriangle.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkanwidget.png b/examples/vulkan/doc/images/hellovulkanwidget.png
new file mode 100644
index 0000000000..b85d4dc596
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkanwidget.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkanwindow.png b/examples/vulkan/doc/images/hellovulkanwindow.png
new file mode 100644
index 0000000000..c55029312c
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkanwindow.png
Binary files differ
diff --git a/examples/vulkan/doc/src/hellovulkantexture.qdoc b/examples/vulkan/doc/src/hellovulkantexture.qdoc
new file mode 100644
index 0000000000..d0e0ca90a8
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkantexture.qdoc
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkantexture
+ \ingroup examples-vulkan
+ \title Hello Vulkan Texture Vulkan Example
+ \brief Shows the basics of rendering with textures in a QVulkanWindow
+
+ The \e{Hello Vulkan Texture Example} builds on \l hellovulkantriangle. Here
+ instead of drawing a single triangle, a triangle strip is drawn in order to
+ get a quad on the screen. This is then textured using a QImage loaded from
+ a .png image file.
+
+ \image hellovulkantexture.png
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkantriangle.qdoc b/examples/vulkan/doc/src/hellovulkantriangle.qdoc
new file mode 100644
index 0000000000..81af776ea1
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkantriangle.qdoc
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkantriangle
+ \ingroup examples-vulkan
+ \title Hello Vulkan Triangle Example
+ \brief Shows the basics of rendering with QVulkanWindow and the Vulkan API
+
+ The \e{Hello Vulkan Triangle Example} builds on \l hellovulkanwindow. This
+ time a full graphics pipeline is created, including a vertex and fragment
+ shader. This pipeline is then used to render a triangle.
+
+ \image hellovulkantriangle.png
+
+ The example also demonstrates multisample antialiasing. Based on the
+ supported sample counts reported by QVulkanWindow::supportedSampleCounts()
+ the example chooses between 8x, 4x, or no multisampling. Once configured
+ via QVulkanWindow::setSamples(), QVulkanWindow takes care of the rest: the
+ additional multisample color buffers are created automatically, and
+ resolving into the swapchain buffers is performed at the end of the default
+ render pass for each frame.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkanwidget.qdoc b/examples/vulkan/doc/src/hellovulkanwidget.qdoc
new file mode 100644
index 0000000000..7987bdeff9
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkanwidget.qdoc
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkanwidget
+ \ingroup examples-vulkan
+ \title Hello Vulkan Widget Example
+ \brief Shows the usage of QVulkanWindow in QWidget applications
+
+ The \e{Hello Vulkan Widget Example} is a variant of \l hellovulkantriangle
+ that embeds the QVulkanWindow into a QWidget-based user interface using
+ QWidget::createWindowContainer().
+
+ \image hellovulkanwidget.png
+
+ The code to set up the Vulkan pipeline and render the triangle is the same
+ as in \l hellovulkantriangle. In addition, this example demonstrates
+ another feature of QVulkanWindow: reading the image content back from the
+ color buffer into a QImage. By clicking the Grab button, the example
+ renders the next frame and follows it up with a transfer operation in order
+ to get the swapchain color buffer content copied into host accessible
+ memory. The image is then saved to disk via QImage::save().
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkanwindow.qdoc b/examples/vulkan/doc/src/hellovulkanwindow.qdoc
new file mode 100644
index 0000000000..06cc9c1c28
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkanwindow.qdoc
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkanwindow
+ \title Hello Vulkan Window Example
+ \ingroup examples-vulkan
+ \brief Shows the basics of using QVulkanWindow
+
+ The \e{Hello Vulkan Window Example} shows the basics of using QVulkanWindow
+ in order to display rendering with the Vulkan graphics API on systems that
+ support this.
+
+ \image hellovulkanwindow.png
+
+ In this example there will be no actual rendering: it simply begins and
+ ends a render pass, which results in clearing the buffers to a fixed value.
+ The color buffer clear value changes on every frame.
+
+ \section1 Startup
+
+ Each Qt application using Vulkan will have to have a \c{Vulkan instance}
+ which encapsulates application-level state and initializes a Vulkan library.
+
+ A QVulkanWindow must always be associated with a QVulkanInstance and hence
+ the example performs instance creation before the window. The
+ QVulkanInstance object must also outlive the window.
+
+ \snippet hellovulkanwindow/main.cpp 0
+
+ The example enables validation layers, when supported. When the requested
+ layers are not present, the request will be ignored. Additional layers and
+ extensions can be enabled in a similar manner.
+
+ \snippet hellovulkanwindow/main.cpp 1
+
+ Once the instance is ready, it is time to create a window. Note that \c w
+ lives on the stack and is declared after \c inst.
+
+ \section1 The QVulkanWindow Subclass
+
+ To add custom functionality to a QVulkanWindow, subclassing is used. This
+ follows the existing patterns from QOpenGLWindow and QOpenGLWidget.
+ However, QVulkanWindow utilizes a separate QVulkanWindowRenderer object.
+ This resembles QQuickFramebufferObject, and allows better separation of the
+ functions that are supposed to be reimplemented.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.h 0
+
+ The QVulkanWindow subclass reimplements the factory function
+ QVulkanWindow::createRenderer(). This simply returns a new instance of the
+ QVulkanWindowRenderer subclass. In order to be able to access various
+ Vulkan resources via the window object, a pointer to the window is passed
+ and stored via the constructor.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 0
+
+ Graphics resource creation and destruction is typically done in one of the
+ init - resource functions.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 1
+
+ \section1 The Actual Rendering
+
+ QVulkanWindow subclasses queue their draw calls in their reimplementation
+ of QVulkanWindowRenderer::startNextFrame(). Once done, they are required to
+ call back QVulkanWindow::frameReady(). The example has no asynchronous
+ command generation, so the frameReady() call is made directly from
+ startNextFrame().
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 2
+
+ To get continuous updates, the example simply invokes
+ QWindow::requestUpdate() in order to schedule a repaint.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
new file mode 100644
index 0000000000..5e52d5e006
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
@@ -0,0 +1,828 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "hellovulkantexture.h"
+#include <QVulkanFunctions>
+#include <QCoreApplication>
+#include <QFile>
+
+// Use a triangle strip to get a quad.
+//
+// Note that the vertex data and the projection matrix assume OpenGL. With
+// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
+// of -1/1. These will be corrected for by an extra transformation when
+// calculating the modelview-projection matrix.
+static float vertexData[] = {
+ // x, y, z, u, v
+ -1, -1, 0, 0, 1,
+ -1, 1, 0, 0, 0,
+ 1, -1, 0, 1, 1,
+ 1, 1, 0, 1, 0
+};
+
+static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(QVulkanWindow *w)
+ : m_window(w)
+{
+}
+
+VkShaderModule VulkanRenderer::createShader(const QString &name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to read shader %s", qPrintable(name));
+ return VK_NULL_HANDLE;
+ }
+ QByteArray blob = file.readAll();
+ file.close();
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkShaderModule shaderModule;
+ VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+
+ return shaderModule;
+}
+
+bool VulkanRenderer::createTexture(const QString &name)
+{
+ QImage img(name);
+ if (img.isNull()) {
+ qWarning("Failed to load image %s", qPrintable(name));
+ return false;
+ }
+
+ // Convert to byte ordered RGBA8. Use premultiplied alpha, see pColorBlendState in the pipeline.
+ img = img.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+
+ QVulkanFunctions *f = m_window->vulkanInstance()->functions();
+ VkDevice dev = m_window->device();
+
+ const bool srgb = QCoreApplication::arguments().contains(QStringLiteral("--srgb"));
+ if (srgb)
+ qDebug("sRGB swapchain was requested, making texture sRGB too");
+
+ m_texFormat = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+
+ // Now we can either map and copy the image data directly, or have to go
+ // through a staging buffer to copy and convert into the internal optimal
+ // tiling format.
+ VkFormatProperties props;
+ f->vkGetPhysicalDeviceFormatProperties(m_window->physicalDevice(), m_texFormat, &props);
+ const bool canSampleLinear = (props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ const bool canSampleOptimal = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ if (!canSampleLinear && !canSampleOptimal) {
+ qWarning("Neither linear nor optimal image sampling is supported for RGBA8");
+ return false;
+ }
+
+ static bool alwaysStage = qEnvironmentVariableIntValue("QT_VK_FORCE_STAGE_TEX");
+
+ if (canSampleLinear && !alwaysStage) {
+ if (!createTextureImage(img.size(), &m_texImage, &m_texMem,
+ VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT,
+ m_window->hostVisibleMemoryIndex()))
+ return false;
+
+ if (!writeLinearImage(img, m_texImage, m_texMem))
+ return false;
+
+ m_texLayoutPending = true;
+ } else {
+ if (!createTextureImage(img.size(), &m_texStaging, &m_texStagingMem,
+ VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ m_window->hostVisibleMemoryIndex()))
+ return false;
+
+ if (!createTextureImage(img.size(), &m_texImage, &m_texMem,
+ VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ m_window->deviceLocalMemoryIndex()))
+ return false;
+
+ if (!writeLinearImage(img, m_texStaging, m_texStagingMem))
+ return false;
+
+ m_texStagingPending = true;
+ }
+
+ VkImageViewCreateInfo viewInfo;
+ memset(&viewInfo, 0, sizeof(viewInfo));
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = m_texImage;
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = m_texFormat;
+ 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_COLOR_BIT;
+ viewInfo.subresourceRange.levelCount = viewInfo.subresourceRange.layerCount = 1;
+
+ VkResult err = m_devFuncs->vkCreateImageView(dev, &viewInfo, nullptr, &m_texView);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image view for texture: %d", err);
+ return false;
+ }
+
+ m_texSize = img.size();
+
+ return true;
+}
+
+bool VulkanRenderer::createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem,
+ VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex)
+{
+ VkDevice dev = m_window->device();
+
+ VkImageCreateInfo imageInfo;
+ memset(&imageInfo, 0, sizeof(imageInfo));
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = m_texFormat;
+ imageInfo.extent.width = size.width();
+ imageInfo.extent.height = size.height();
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.arrayLayers = 1;
+ imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.tiling = tiling;
+ imageInfo.usage = usage;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ VkResult err = m_devFuncs->vkCreateImage(dev, &imageInfo, nullptr, image);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create linear image for texture: %d", err);
+ return false;
+ }
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetImageMemoryRequirements(dev, *image, &memReq);
+
+ VkMemoryAllocateInfo allocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ memIndex
+ };
+ qDebug("allocating %u bytes for texture image", uint32_t(memReq.size));
+
+ err = m_devFuncs->vkAllocateMemory(dev, &allocInfo, nullptr, mem);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to allocate memory for linear image: %d", err);
+ return false;
+ }
+
+ err = m_devFuncs->vkBindImageMemory(dev, *image, *mem, 0);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to bind linear image memory: %d", err);
+ return false;
+ }
+
+ return true;
+}
+
+bool VulkanRenderer::writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory)
+{
+ VkDevice dev = m_window->device();
+
+ VkImageSubresource subres = {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 0, // mip level
+ 0
+ };
+ VkSubresourceLayout layout;
+ m_devFuncs->vkGetImageSubresourceLayout(dev, image, &subres, &layout);
+
+ uchar *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, memory, layout.offset, layout.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map memory for linear image: %d", err);
+ return false;
+ }
+
+ for (int y = 0; y < img.height(); ++y) {
+ const uchar *line = img.constScanLine(y);
+ memcpy(p, line, img.width() * 4);
+ p += layout.rowPitch;
+ }
+
+ m_devFuncs->vkUnmapMemory(dev, memory);
+ return true;
+}
+
+void VulkanRenderer::ensureTexture()
+{
+ if (!m_texLayoutPending && !m_texStagingPending)
+ return;
+
+ Q_ASSERT(m_texLayoutPending != m_texStagingPending);
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ VkImageMemoryBarrier barrier;
+ memset(&barrier, 0, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.levelCount = barrier.subresourceRange.layerCount = 1;
+
+ if (m_texLayoutPending) {
+ m_texLayoutPending = false;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.image = m_texImage;
+
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+ } else {
+ m_texStagingPending = false;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.image = m_texStaging;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.image = m_texImage;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ VkImageCopy copyInfo;
+ memset(&copyInfo, 0, sizeof(copyInfo));
+ copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.srcSubresource.layerCount = 1;
+ copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.dstSubresource.layerCount = 1;
+ copyInfo.extent.width = m_texSize.width();
+ copyInfo.extent.height = m_texSize.height();
+ copyInfo.extent.depth = 1;
+ m_devFuncs->vkCmdCopyImage(cb, m_texStaging, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ m_texImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyInfo);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.image = m_texImage;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+ }
+}
+
+void VulkanRenderer::initResources()
+{
+ qDebug("initResources");
+
+ VkDevice dev = m_window->device();
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
+
+ // The setup is similar to hellovulkantriangle. The difference is the
+ // presence of a second vertex attribute (texcoord), a sampler, and that we
+ // need blending.
+
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+ qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
+ const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
+ const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
+ bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind buffer memory: %d", err);
+
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, vertexData, sizeof(vertexData));
+ QMatrix4x4 ident;
+ memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
+ memcpy(p + offset, ident.constData(), 16 * sizeof(float));
+ m_uniformBufInfo[i].buffer = m_buf;
+ m_uniformBufInfo[i].offset = offset;
+ m_uniformBufInfo[i].range = uniformAllocSize;
+ }
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 5 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0
+ },
+ { // texcoord
+ 1,
+ 0,
+ VK_FORMAT_R32G32_SFLOAT,
+ 3 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = 2;
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Sampler.
+ VkSamplerCreateInfo samplerInfo;
+ memset(&samplerInfo, 0, sizeof(samplerInfo));
+ samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ samplerInfo.magFilter = VK_FILTER_NEAREST;
+ samplerInfo.minFilter = VK_FILTER_NEAREST;
+ samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ err = m_devFuncs->vkCreateSampler(dev, &samplerInfo, nullptr, &m_sampler);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create sampler: %d", err);
+
+ // Texture.
+ if (!createTexture(QStringLiteral(":/qt256.png")))
+ qFatal("Failed to create texture");
+
+ // Set up descriptor set and its layout.
+ VkDescriptorPoolSize descPoolSizes[2] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, uint32_t(concurrentFrameCount) }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = concurrentFrameCount;
+ descPoolInfo.poolSizeCount = 2;
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBinding[2] =
+ {
+ {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ },
+ {
+ 1, // binding
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ nullptr
+ }
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ 2, // bindingCount
+ layoutBinding
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_descPool,
+ 1,
+ &m_descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ VkWriteDescriptorSet descWrite[2];
+ memset(descWrite, 0, sizeof(descWrite));
+ descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[0].dstSet = m_descSet[i];
+ descWrite[0].dstBinding = 0;
+ descWrite[0].descriptorCount = 1;
+ descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descWrite[0].pBufferInfo = &m_uniformBufInfo[i];
+
+ VkDescriptorImageInfo descImageInfo = {
+ m_sampler,
+ m_texView,
+ VK_IMAGE_LAYOUT_GENERAL
+ };
+
+ descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[1].dstSet = m_descSet[i];
+ descWrite[1].dstBinding = 1;
+ descWrite[1].descriptorCount = 1;
+ descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descWrite[1].pImageInfo = &descImageInfo;
+
+ m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr);
+ }
+
+ // Pipeline cache
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ // Pipeline layout
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ // Shaders
+ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv"));
+ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv"));
+
+ // Graphics pipeline
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ vertShaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fragShaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
+ // This way the pipeline does not need to be touched when resizing the window.
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ // assume pre-multiplied alpha, blend, write out all of rgba
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ att.blendEnable = VK_TRUE;
+ att.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
+ att.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ att.colorBlendOp = VK_BLEND_OP_ADD;
+ att.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ att.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ att.alphaBlendOp = VK_BLEND_OP_ADD;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ if (vertShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
+ if (fragShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
+}
+
+void VulkanRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+
+ // Projection matrix
+ m_proj = *m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void VulkanRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void VulkanRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+
+ VkDevice dev = m_window->device();
+
+ if (m_sampler) {
+ m_devFuncs->vkDestroySampler(dev, m_sampler, nullptr);
+ m_sampler = VK_NULL_HANDLE;
+ }
+
+ if (m_texStaging) {
+ m_devFuncs->vkDestroyImage(dev, m_texStaging, nullptr);
+ m_texStaging = VK_NULL_HANDLE;
+ }
+
+ if (m_texStagingMem) {
+ m_devFuncs->vkFreeMemory(dev, m_texStagingMem, nullptr);
+ m_texStagingMem = VK_NULL_HANDLE;
+ }
+
+ if (m_texView) {
+ m_devFuncs->vkDestroyImageView(dev, m_texView, nullptr);
+ m_texView = VK_NULL_HANDLE;
+ }
+
+ if (m_texImage) {
+ m_devFuncs->vkDestroyImage(dev, m_texImage, nullptr);
+ m_texImage = VK_NULL_HANDLE;
+ }
+
+ if (m_texMem) {
+ m_devFuncs->vkFreeMemory(dev, m_texMem, nullptr);
+ m_texMem = VK_NULL_HANDLE;
+ }
+
+ if (m_pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
+ m_pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
+ m_pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
+ m_descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
+ m_descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_buf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
+ m_buf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+}
+
+void VulkanRenderer::startNextFrame()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ // Add the necessary barriers and do the host-linear -> device-optimal copy, if not yet done.
+ ensureTexture();
+
+ VkClearColorValue clearColor = { 0, 0, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
+ UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ QMatrix4x4 m = m_proj;
+ m.rotate(m_rotation, 0, 0, 1);
+ memcpy(p, m.constData(), 16 * sizeof(float));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Not exactly a real animation system, just advance on every frame for now.
+ m_rotation += 1.0f;
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_descSet[m_window->currentFrame()], 0, nullptr);
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
+
+ VkViewport viewport;
+ viewport.x = viewport.y = 0;
+ viewport.width = sz.width();
+ viewport.height = sz.height();
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor;
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = viewport.width;
+ scissor.extent.height = viewport.height;
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.h b/examples/vulkan/hellovulkantexture/hellovulkantexture.h
new file mode 100644
index 0000000000..a8c96d1987
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+#include <QImage>
+
+class VulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ VulkanRenderer(QVulkanWindow *w);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ VkShaderModule createShader(const QString &name);
+ bool createTexture(const QString &name);
+ bool createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem,
+ VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex);
+ bool writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory);
+ void ensureTexture();
+
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_buf = VK_NULL_HANDLE;
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkDescriptorPool m_descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ VkSampler m_sampler = VK_NULL_HANDLE;
+ VkImage m_texImage = VK_NULL_HANDLE;
+ VkDeviceMemory m_texMem = VK_NULL_HANDLE;
+ bool m_texLayoutPending = false;
+ VkImageView m_texView = VK_NULL_HANDLE;
+ VkImage m_texStaging = VK_NULL_HANDLE;
+ VkDeviceMemory m_texStagingMem = VK_NULL_HANDLE;
+ bool m_texStagingPending = false;
+ QSize m_texSize;
+ VkFormat m_texFormat;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0.0f;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.pro b/examples/vulkan/hellovulkantexture/hellovulkantexture.pro
new file mode 100644
index 0000000000..59bfcda715
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.pro
@@ -0,0 +1,7 @@
+HEADERS += hellovulkantexture.h
+SOURCES += hellovulkantexture.cpp main.cpp
+RESOURCES += hellovulkantexture.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkantexture
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc b/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc
new file mode 100644
index 0000000000..04e7cda859
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>texture_vert.spv</file>
+ <file>texture_frag.spv</file>
+ <file>qt256.png</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkantexture/main.cpp b/examples/vulkan/hellovulkantexture/main.cpp
new file mode 100644
index 0000000000..1144463b70
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/main.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkantexture.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ w.setPreferredColorFormats(QVector<VkFormat>() << VK_FORMAT_B8G8R8A8_SRGB);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkantexture/qt256.png b/examples/vulkan/hellovulkantexture/qt256.png
new file mode 100644
index 0000000000..30c621c9c6
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/qt256.png
Binary files differ
diff --git a/examples/vulkan/hellovulkantexture/texture.frag b/examples/vulkan/hellovulkantexture/texture.frag
new file mode 100644
index 0000000000..e6021fe905
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ fragColor = texture(tex, v_texcoord);
+}
diff --git a/examples/vulkan/hellovulkantexture/texture.vert b/examples/vulkan/hellovulkantexture/texture.vert
new file mode 100644
index 0000000000..de486cb772
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = texcoord;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/examples/vulkan/hellovulkantexture/texture_frag.spv b/examples/vulkan/hellovulkantexture/texture_frag.spv
new file mode 100644
index 0000000000..7521ef6eef
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkantexture/texture_vert.spv b/examples/vulkan/hellovulkantexture/texture_vert.spv
new file mode 100644
index 0000000000..6292c0de31
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro
new file mode 100644
index 0000000000..db016da3ac
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro
@@ -0,0 +1,12 @@
+HEADERS += \
+ ../shared/trianglerenderer.h
+
+SOURCES += \
+ main.cpp \
+ ../shared/trianglerenderer.cpp
+
+RESOURCES += hellovulkantriangle.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkantriangle
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc
new file mode 100644
index 0000000000..489fc7295a
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color_vert.spv">../shared/color_vert.spv</file>
+ <file alias="color_frag.spv">../shared/color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkantriangle/main.cpp b/examples/vulkan/hellovulkantriangle/main.cpp
new file mode 100644
index 0000000000..d3eef2e14a
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/main.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "../shared/trianglerenderer.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new TriangleRenderer(this, true); // try MSAA, when available
+}
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
new file mode 100644
index 0000000000..ecab104399
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
@@ -0,0 +1,182 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "hellovulkanwidget.h"
+#include <QVulkanFunctions>
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QTextEdit>
+#include <QPushButton>
+#include <QLCDNumber>
+#include <QFileDialog>
+#include <QMessageBox>
+
+MainWindow::MainWindow(VulkanWindow *w)
+ : m_window(w)
+{
+ QWidget *wrapper = QWidget::createWindowContainer(w);
+
+ m_info = new QTextEdit;
+ m_info->setReadOnly(true);
+
+ m_number = new QLCDNumber(3);
+ m_number->setSegmentStyle(QLCDNumber::Filled);
+
+ QPushButton *grabButton = new QPushButton(tr("&Grab"));
+ grabButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(grabButton, &QPushButton::clicked, this, &MainWindow::onGrabRequested);
+
+ QPushButton *quitButton = new QPushButton(tr("&Quit"));
+ quitButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(m_info, 2);
+ layout->addWidget(m_number, 1);
+ layout->addWidget(wrapper, 5);
+ layout->addWidget(grabButton, 1);
+ layout->addWidget(quitButton, 1);
+ setLayout(layout);
+}
+
+void MainWindow::onVulkanInfoReceived(const QString &text)
+{
+ m_info->setText(text);
+}
+
+void MainWindow::onFrameQueued(int colorValue)
+{
+ m_number->display(colorValue);
+}
+
+void MainWindow::onGrabRequested()
+{
+ if (!m_window->supportsGrab()) {
+ QMessageBox::warning(this, tr("Cannot grab"), tr("This swapchain does not support readbacks."));
+ return;
+ }
+
+ QImage img = m_window->grab();
+
+ // Our startNextFrame() implementation is synchronous so img is ready to be
+ // used right here.
+
+ QFileDialog fd(this);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setDefaultSuffix("png");
+ fd.selectFile("test.png");
+ if (fd.exec() == QDialog::Accepted)
+ img.save(fd.selectedFiles().first());
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(VulkanWindow *w)
+ : TriangleRenderer(w)
+{
+}
+
+void VulkanRenderer::initResources()
+{
+ TriangleRenderer::initResources();
+
+ QVulkanInstance *inst = m_window->vulkanInstance();
+ m_devFuncs = inst->deviceFunctions(m_window->device());
+
+ QString info;
+ info += QString().sprintf("Number of physical devices: %d\n", m_window->availablePhysicalDevices().count());
+
+ QVulkanFunctions *f = inst->functions();
+ VkPhysicalDeviceProperties props;
+ f->vkGetPhysicalDeviceProperties(m_window->physicalDevice(), &props);
+ info += QString().sprintf("Active physical device name: '%s' version %d.%d.%d\nAPI version %d.%d.%d\n",
+ props.deviceName,
+ VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion),
+ VK_VERSION_PATCH(props.driverVersion),
+ VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion),
+ VK_VERSION_PATCH(props.apiVersion));
+
+ info += QStringLiteral("Supported instance layers:\n");
+ for (const QVulkanLayer &layer : inst->supportedLayers())
+ info += QString().sprintf(" %s v%u\n", layer.name.constData(), layer.version);
+ info += QStringLiteral("Enabled instance layers:\n");
+ for (const QByteArray &layer : inst->layers())
+ info += QString().sprintf(" %s\n", layer.constData());
+
+ info += QStringLiteral("Supported instance extensions:\n");
+ for (const QVulkanExtension &ext : inst->supportedExtensions())
+ info += QString().sprintf(" %s v%u\n", ext.name.constData(), ext.version);
+ info += QStringLiteral("Enabled instance extensions:\n");
+ for (const QByteArray &ext : inst->extensions())
+ info += QString().sprintf(" %s\n", ext.constData());
+
+ info += QString().sprintf("Color format: %u\nDepth-stencil format: %u\n",
+ m_window->colorFormat(), m_window->depthStencilFormat());
+
+ info += QStringLiteral("Supported sample counts:");
+ QList<int> sampleCounts = m_window->supportedSampleCounts().toList();
+ std::sort(sampleCounts.begin(), sampleCounts.end());
+ for (int count : sampleCounts)
+ info += QLatin1Char(' ') + QString::number(count);
+ info += QLatin1Char('\n');
+
+ emit static_cast<VulkanWindow *>(m_window)->vulkanInfoReceived(info);
+}
+
+void VulkanRenderer::startNextFrame()
+{
+ TriangleRenderer::startNextFrame();
+ emit static_cast<VulkanWindow *>(m_window)->frameQueued(int(m_rotation) % 360);
+}
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h
new file mode 100644
index 0000000000..b1f4824006
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "../shared/trianglerenderer.h"
+#include <QWidget>
+
+class VulkanWindow;
+
+QT_BEGIN_NAMESPACE
+class QTextEdit;
+class QLCDNumber;
+QT_END_NAMESPACE
+
+class MainWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ MainWindow(VulkanWindow *w);
+
+public slots:
+ void onVulkanInfoReceived(const QString &text);
+ void onFrameQueued(int colorValue);
+ void onGrabRequested();
+
+private:
+ VulkanWindow *m_window;
+ QTextEdit *m_info;
+ QLCDNumber *m_number;
+};
+
+class VulkanRenderer : public TriangleRenderer
+{
+public:
+ VulkanRenderer(VulkanWindow *w);
+
+ void initResources() override;
+ void startNextFrame() override;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+ Q_OBJECT
+
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+
+signals:
+ void vulkanInfoReceived(const QString &text);
+ void frameQueued(int colorValue);
+};
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro
new file mode 100644
index 0000000000..7b87d7f210
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro
@@ -0,0 +1,16 @@
+QT += widgets
+
+HEADERS += \
+ hellovulkanwidget.h \
+ ../shared/trianglerenderer.h
+
+SOURCES += \
+ hellovulkanwidget.cpp \
+ main.cpp \
+ ../shared/trianglerenderer.cpp
+
+RESOURCES += hellovulkanwidget.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkanwidget
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc
new file mode 100644
index 0000000000..489fc7295a
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color_vert.spv">../shared/color_vert.spv</file>
+ <file alias="color_frag.spv">../shared/color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkanwidget/main.cpp b/examples/vulkan/hellovulkanwidget/main.cpp
new file mode 100644
index 0000000000..320e015e67
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/main.cpp
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkanwidget.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow *vulkanWindow = new VulkanWindow;
+ vulkanWindow->setVulkanInstance(&inst);
+
+ MainWindow mainWindow(vulkanWindow);
+ QObject::connect(vulkanWindow, &VulkanWindow::vulkanInfoReceived, &mainWindow, &MainWindow::onVulkanInfoReceived);
+ QObject::connect(vulkanWindow, &VulkanWindow::frameQueued, &mainWindow, &MainWindow::onFrameQueued);
+
+ mainWindow.resize(1024, 768);
+ mainWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp
new file mode 100644
index 0000000000..0a7d1d4174
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "hellovulkanwindow.h"
+#include <QVulkanFunctions>
+
+//! [0]
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(QVulkanWindow *w)
+ : m_window(w)
+{
+}
+//! [0]
+
+//! [1]
+void VulkanRenderer::initResources()
+{
+ qDebug("initResources");
+
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
+}
+//! [1]
+
+void VulkanRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+}
+
+void VulkanRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void VulkanRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+}
+
+//! [2]
+void VulkanRenderer::startNextFrame()
+{
+ m_green += 0.005f;
+ if (m_green > 1.0f)
+ m_green = 0.0f;
+
+ VkClearColorValue clearColor = { 0.0f, m_green, 0.0f, 1.0f };
+ VkClearDepthStencilValue clearDS = { 1.0f, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ const QSize sz = m_window->swapChainImageSize();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ // Do nothing else. We will just clear to green, changing the component on
+ // every invocation. This also helps verifying the rate to which the thread
+ // is throttled to. (The elapsed time between startNextFrame calls should
+ // typically be around 16 ms. Note that rendering is 2 frames ahead of what
+ // is displayed.)
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
+//! [2]
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h
new file mode 100644
index 0000000000..5f52e402ca
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+
+//! [0]
+class VulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ VulkanRenderer(QVulkanWindow *w);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+ float m_green = 0;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
+//! [0]
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro
new file mode 100644
index 0000000000..8f7d9494e2
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro
@@ -0,0 +1,6 @@
+HEADERS += hellovulkanwindow.h
+SOURCES += hellovulkanwindow.cpp main.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkanwindow
+INSTALLS += target
diff --git a/src/corelib/doc/snippets/signalmapper/filereader.cpp b/examples/vulkan/hellovulkanwindow/main.cpp
index 674f73d671..313c28f9e0 100644
--- a/src/corelib/doc/snippets/signalmapper/filereader.cpp
+++ b/examples/vulkan/hellovulkanwindow/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
@@ -48,70 +48,46 @@
**
****************************************************************************/
-#include <QtGui>
-#include "filereader.h"
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkanwindow.h"
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
-FileReader::FileReader(QWidget *parent)
- : QWidget(parent)
+int main(int argc, char *argv[])
{
- textEdit = new QTextEdit;
+ QGuiApplication app(argc, argv);
- taxFileButton = new QPushButton("Tax File");
- accountFileButton = new QPushButton("Accounts File");
- reportFileButton = new QPushButton("Report File");
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
//! [0]
- signalMapper = new QSignalMapper(this);
- signalMapper->setMapping(taxFileButton, QString("taxfile.txt"));
- signalMapper->setMapping(accountFileButton, QString("accountsfile.txt"));
- signalMapper->setMapping(reportFileButton, QString("reportfile.txt"));
-
- connect(taxFileButton, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
- connect(accountFileButton, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
- connect(reportFileButton, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
//! [0]
//! [1]
- connect(signalMapper, SIGNAL(mapped(QString)),
- this, SLOT(readFile(QString)));
-//! [1]
-
-/*
-//! [2]
- //slower due to signature normalization at runtime
-
- connect(signalMapper, SIGNAL(mapped(QString)),
- this, SLOT(readFile(QString)));
-//! [2]
-*/
- QHBoxLayout *buttonLayout = new QHBoxLayout;
- buttonLayout->addWidget(taxFileButton);
- buttonLayout->addWidget(accountFileButton);
- buttonLayout->addWidget(reportFileButton);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(textEdit);
- mainLayout->addLayout(buttonLayout);
-
- setLayout(mainLayout);
-}
-
-void FileReader::readFile(const QString &filename)
-{
- QFile file(filename);
-
- if (!file.open(QIODevice::ReadOnly)) {
- QMessageBox::information(this, tr("Unable to open file"),
- file.errorString());
- return;
- }
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ w.resize(1024, 768);
+ w.show();
+//! [1]
- QTextStream in(&file);
- textEdit->setPlainText(in.readAll());
+ return app.exec();
}
-
diff --git a/examples/vulkan/shared/color.frag b/examples/vulkan/shared/color.frag
new file mode 100644
index 0000000000..375587662f
--- /dev/null
+++ b/examples/vulkan/shared/color.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(v_color, 1.0);
+}
diff --git a/examples/vulkan/shared/color.vert b/examples/vulkan/shared/color.vert
new file mode 100644
index 0000000000..02492c0e65
--- /dev/null
+++ b/examples/vulkan/shared/color.vert
@@ -0,0 +1,18 @@
+#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;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/examples/vulkan/shared/color_frag.spv b/examples/vulkan/shared/color_frag.spv
new file mode 100644
index 0000000000..30e33b76ca
--- /dev/null
+++ b/examples/vulkan/shared/color_frag.spv
Binary files differ
diff --git a/examples/vulkan/shared/color_vert.spv b/examples/vulkan/shared/color_vert.spv
new file mode 100644
index 0000000000..a1f42e3119
--- /dev/null
+++ b/examples/vulkan/shared/color_vert.spv
Binary files differ
diff --git a/examples/vulkan/shared/trianglerenderer.cpp b/examples/vulkan/shared/trianglerenderer.cpp
new file mode 100644
index 0000000000..a0800080a0
--- /dev/null
+++ b/examples/vulkan/shared/trianglerenderer.cpp
@@ -0,0 +1,513 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include "trianglerenderer.h"
+#include <QVulkanFunctions>
+#include <QFile>
+
+// Note that the vertex data and the projection matrix assume OpenGL. With
+// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
+// of -1/1. These will be corrected for by an extra transformation when
+// calculating the modelview-projection matrix.
+static float vertexData[] = {
+ 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
+};
+
+static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+TriangleRenderer::TriangleRenderer(QVulkanWindow *w, bool msaa)
+ : m_window(w)
+{
+ if (msaa) {
+ QSet<int> counts = w->supportedSampleCounts();
+ qDebug() << "Supported sample counts:" << counts;
+ for (int s = 16; s >= 4; s /= 2) {
+ if (counts.contains(s)) {
+ qDebug("Requesting sample count %d", s);
+ m_window->setSampleCount(s);
+ break;
+ }
+ }
+ }
+}
+
+VkShaderModule TriangleRenderer::createShader(const QString &name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to read shader %s", qPrintable(name));
+ return VK_NULL_HANDLE;
+ }
+ QByteArray blob = file.readAll();
+ file.close();
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkShaderModule shaderModule;
+ VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+
+ return shaderModule;
+}
+
+void TriangleRenderer::initResources()
+{
+ qDebug("initResources");
+
+ VkDevice dev = m_window->device();
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
+
+ // Prepare the vertex and uniform data. The vertex data will never
+ // change so one buffer is sufficient regardless of the value of
+ // QVulkanWindow::CONCURRENT_FRAME_COUNT. Uniform data is changing per
+ // frame however so active frames have to have a dedicated copy.
+
+ // Use just one memory allocation and one buffer. We will then specify the
+ // appropriate offsets for uniform buffers in the VkDescriptorBufferInfo.
+ // Have to watch out for
+ // VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment, though.
+
+ // The uniform buffer is not strictly required in this example, we could
+ // have used push constants as well since our single matrix (64 bytes) fits
+ // into the spec mandated minimum limit of 128 bytes. However, once that
+ // limit is not sufficient, the per-frame buffers, as shown below, will
+ // become necessary.
+
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+ qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
+ const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
+ const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
+ bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind buffer memory: %d", err);
+
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, vertexData, sizeof(vertexData));
+ QMatrix4x4 ident;
+ memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
+ memcpy(p + offset, ident.constData(), 16 * sizeof(float));
+ m_uniformBufInfo[i].buffer = m_buf;
+ m_uniformBufInfo[i].offset = offset;
+ m_uniformBufInfo[i].range = uniformAllocSize;
+ }
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 5 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32_SFLOAT,
+ 0
+ },
+ { // color
+ 1,
+ 0,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 2 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = 2;
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Set up descriptor set and its layout.
+ VkDescriptorPoolSize descPoolSizes = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = concurrentFrameCount;
+ descPoolInfo.poolSizeCount = 1;
+ descPoolInfo.pPoolSizes = &descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBinding = {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ 1,
+ &layoutBinding
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_descPool,
+ 1,
+ &m_descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ VkWriteDescriptorSet descWrite;
+ memset(&descWrite, 0, sizeof(descWrite));
+ descWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite.dstSet = m_descSet[i];
+ descWrite.descriptorCount = 1;
+ descWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descWrite.pBufferInfo = &m_uniformBufInfo[i];
+ m_devFuncs->vkUpdateDescriptorSets(dev, 1, &descWrite, 0, nullptr);
+ }
+
+ // Pipeline cache
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ // Pipeline layout
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ // Shaders
+ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/color_vert.spv"));
+ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/color_frag.spv"));
+
+ // Graphics pipeline
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ vertShaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fragShaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
+ // This way the pipeline does not need to be touched when resizing the window.
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_NONE; // we want the back face as well
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ // Enable multisampling.
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ // no blend, write out all of rgba
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ if (vertShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
+ if (fragShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
+}
+
+void TriangleRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+
+ // Projection matrix
+ m_proj = *m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TriangleRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void TriangleRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+
+ VkDevice dev = m_window->device();
+
+ if (m_pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
+ m_pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
+ m_pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
+ m_descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
+ m_descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_buf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
+ m_buf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+}
+
+void TriangleRenderer::startNextFrame()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ VkClearColorValue clearColor = { 0, 0, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
+ UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ QMatrix4x4 m = m_proj;
+ m.rotate(m_rotation, 0, 1, 0);
+ memcpy(p, m.constData(), 16 * sizeof(float));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Not exactly a real animation system, just advance on every frame for now.
+ m_rotation += 1.0f;
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_descSet[m_window->currentFrame()], 0, nullptr);
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
+
+ VkViewport viewport;
+ viewport.x = viewport.y = 0;
+ viewport.width = sz.width();
+ viewport.height = sz.height();
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor;
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = viewport.width;
+ scissor.extent.height = viewport.height;
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 3, 1, 0, 0);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
diff --git a/examples/vulkan/shared/trianglerenderer.h b/examples/vulkan/shared/trianglerenderer.h
new file mode 100644
index 0000000000..9a33291a95
--- /dev/null
+++ b/examples/vulkan/shared/trianglerenderer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+
+class TriangleRenderer : public QVulkanWindowRenderer
+{
+public:
+ TriangleRenderer(QVulkanWindow *w, bool msaa = false);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+protected:
+ VkShaderModule createShader(const QString &name);
+
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_buf = VK_NULL_HANDLE;
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkDescriptorPool m_descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0.0f;
+};
diff --git a/examples/vulkan/vulkan.pro b/examples/vulkan/vulkan.pro
new file mode 100644
index 0000000000..ef5496bcd4
--- /dev/null
+++ b/examples/vulkan/vulkan.pro
@@ -0,0 +1,7 @@
+TEMPLATE = subdirs
+
+SUBDIRS = hellovulkanwindow \
+ hellovulkantriangle \
+ hellovulkantexture
+
+qtHaveModule(widgets): SUBDIRS += hellovulkanwidget
diff --git a/examples/widgets/graphicsview/collidingmice/mouse.cpp b/examples/widgets/graphicsview/collidingmice/mouse.cpp
index b94c650c18..cc1a15cd82 100644
--- a/examples/widgets/graphicsview/collidingmice/mouse.cpp
+++ b/examples/widgets/graphicsview/collidingmice/mouse.cpp
@@ -54,7 +54,7 @@
#include <QPainter>
#include <QStyleOption>
-#include <math.h>
+#include <cmath>
static const double Pi = 3.14159265358979323846264338327950288419717;
static double TwoPi = 2.0 * Pi;
@@ -140,9 +140,7 @@ void Mouse::advance(int step)
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
- qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
- if (lineToCenter.dy() < 0)
- angleToCenter = TwoPi - angleToCenter;
+ qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
@@ -171,9 +169,7 @@ void Mouse::advance(int step)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
- qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
- if (lineToMouse.dy() < 0)
- angleToMouse = TwoPi - angleToMouse;
+ qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp
index 012b9ea2ed..ae7fa7af90 100644
--- a/examples/widgets/graphicsview/diagramscene/arrow.cpp
+++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp
@@ -51,7 +51,7 @@
#include "arrow.h"
-#include <math.h>
+#include <cmath>
#include <QPen>
#include <QPainter>
@@ -132,9 +132,7 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
setLine(QLineF(intersectPoint, myStartItem->pos()));
//! [5] //! [6]
- double angle = ::acos(line().dx() / line().length());
- if (line().dy() >= 0)
- angle = (Pi * 2) - angle;
+ double angle = std::atan2(-line().dy(), line().dx());
QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize,
cos(angle + Pi / 3) * arrowSize);
diff --git a/examples/widgets/graphicsview/elasticnodes/edge.cpp b/examples/widgets/graphicsview/elasticnodes/edge.cpp
index e794e803cf..d9e4c62e34 100644
--- a/examples/widgets/graphicsview/elasticnodes/edge.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/edge.cpp
@@ -51,12 +51,11 @@
#include "edge.h"
#include "node.h"
-#include <math.h>
+#include <cmath>
#include <QPainter>
static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
//! [0]
Edge::Edge(Node *sourceNode, Node *destNode)
@@ -139,9 +138,7 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
//! [6]
// Draw the arrows
- double angle = ::acos(line.dx() / line.length());
- if (line.dy() >= 0)
- angle = TwoPi - angle;
+ double angle = std::atan2(-line.dy(), line.dx());
QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize,
cos(angle + Pi / 3) * arrowSize);
diff --git a/examples/widgets/itemviews/chart/pieview.cpp b/examples/widgets/itemviews/chart/pieview.cpp
index fb439fae67..942bbe5ca5 100644
--- a/examples/widgets/itemviews/chart/pieview.cpp
+++ b/examples/widgets/itemviews/chart/pieview.cpp
@@ -125,9 +125,9 @@ QModelIndex PieView::indexAt(const QPoint &point) const
return QModelIndex();
// Determine the angle of the point.
- double angle = (180 / M_PI) * std::acos(cx / d);
- if (cy < 0)
- angle = 360 - angle;
+ double angle = (180 / M_PI) * std::atan2(cy, cx);
+ if (angle < 0)
+ angle = 360 + angle;
// Find the relevant slice of the pie.
double startAngle = 0.0;
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
index 10e3dd045a..afceddfca1 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
@@ -63,7 +63,6 @@
#include <QFileDialog>
#include <QDialogButtonBox>
#include <QMessageBox>
-#include <QSignalMapper>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp
index e0f208d336..fade2dfc96 100644
--- a/examples/xml/dombookmarks/mainwindow.cpp
+++ b/examples/xml/dombookmarks/mainwindow.cpp
@@ -58,13 +58,13 @@ MainWindow::MainWindow()
xbelTree = new XbelTree;
setCentralWidget(xbelTree);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("DOM Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
void MainWindow::open()
@@ -80,8 +80,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -102,8 +102,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -119,37 +119,21 @@ void MainWindow::about()
"documents."));
}
-void MainWindow::createActions()
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
diff --git a/examples/xml/dombookmarks/mainwindow.h b/examples/xml/dombookmarks/mainwindow.h
index 6d490caf64..0a8c7bdd82 100644
--- a/examples/xml/dombookmarks/mainwindow.h
+++ b/examples/xml/dombookmarks/mainwindow.h
@@ -68,18 +68,9 @@ public slots:
void about();
private:
- void createActions();
void createMenus();
XbelTree *xbelTree;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
#endif
diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp
index 82afc48bd9..f7ff1de638 100644
--- a/examples/xml/dombookmarks/xbeltree.cpp
+++ b/examples/xml/dombookmarks/xbeltree.cpp
@@ -52,6 +52,18 @@
#include "xbeltree.h"
+enum { DomElementRole = Qt::UserRole + 1 };
+
+Q_DECLARE_METATYPE(QDomElement)
+
+static inline QString titleElement() { return QStringLiteral("title"); }
+static inline QString folderElement() { return QStringLiteral("folder"); }
+static inline QString bookmarkElement() { return QStringLiteral("bookmark"); }
+
+static inline QString versionAttribute() { return QStringLiteral("version"); }
+static inline QString hrefAttribute() { return QStringLiteral("href"); }
+static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
XbelTree::XbelTree(QWidget *parent)
: QTreeWidget(parent)
{
@@ -68,6 +80,24 @@ XbelTree::XbelTree(QWidget *parent)
bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
}
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void XbelTree::contextMenuEvent(QContextMenuEvent *event)
+{
+ const QTreeWidgetItem *item = itemAt(event->pos());
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(event->globalPos());
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
bool XbelTree::read(QIODevice *device)
{
QString errorStr;
@@ -89,8 +119,8 @@ bool XbelTree::read(QIODevice *device)
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL file."));
return false;
- } else if (root.hasAttribute("version")
- && root.attribute("version") != "1.0") {
+ } else if (root.hasAttribute(versionAttribute())
+ && root.attribute(versionAttribute()) != QLatin1String("1.0")) {
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL version 1.0 "
"file."));
@@ -99,22 +129,20 @@ bool XbelTree::read(QIODevice *device)
clear();
- disconnect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateDomElement(QTreeWidgetItem*,int)));
+ disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
- QDomElement child = root.firstChildElement("folder");
+ QDomElement child = root.firstChildElement(folderElement());
while (!child.isNull()) {
parseFolderElement(child);
- child = child.nextSiblingElement("folder");
+ child = child.nextSiblingElement(folderElement());
}
- connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateDomElement(QTreeWidgetItem*,int)));
+ connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
return true;
}
-bool XbelTree::write(QIODevice *device)
+bool XbelTree::write(QIODevice *device) const
{
const int IndentSize = 4;
@@ -123,21 +151,21 @@ bool XbelTree::write(QIODevice *device)
return true;
}
-void XbelTree::updateDomElement(QTreeWidgetItem *item, int column)
+void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column)
{
- QDomElement element = domElementForItem.value(item);
+ QDomElement element = item->data(0, DomElementRole).value<QDomElement>();
if (!element.isNull()) {
if (column == 0) {
- QDomElement oldTitleElement = element.firstChildElement("title");
- QDomElement newTitleElement = domDocument.createElement("title");
+ QDomElement oldTitleElement = element.firstChildElement(titleElement());
+ QDomElement newTitleElement = domDocument.createElement(titleElement());
QDomText newTitleText = domDocument.createTextNode(item->text(0));
newTitleElement.appendChild(newTitleText);
element.replaceChild(newTitleElement, oldTitleElement);
} else {
- if (element.tagName() == "bookmark")
- element.setAttribute("href", item->text(1));
+ if (element.tagName() == bookmarkElement())
+ element.setAttribute(hrefAttribute(), item->text(1));
}
}
}
@@ -147,7 +175,7 @@ void XbelTree::parseFolderElement(const QDomElement &element,
{
QTreeWidgetItem *item = createItem(element, parentItem);
- QString title = element.firstChildElement("title").text();
+ QString title = element.firstChildElement(titleElement()).text();
if (title.isEmpty())
title = QObject::tr("Folder");
@@ -155,25 +183,25 @@ void XbelTree::parseFolderElement(const QDomElement &element,
item->setIcon(0, folderIcon);
item->setText(0, title);
- bool folded = (element.attribute("folded") != "no");
+ bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no"));
setItemExpanded(item, !folded);
QDomElement child = element.firstChildElement();
while (!child.isNull()) {
- if (child.tagName() == "folder") {
+ if (child.tagName() == folderElement()) {
parseFolderElement(child, item);
- } else if (child.tagName() == "bookmark") {
+ } else if (child.tagName() == bookmarkElement()) {
QTreeWidgetItem *childItem = createItem(child, item);
- QString title = child.firstChildElement("title").text();
+ QString title = child.firstChildElement(titleElement()).text();
if (title.isEmpty())
title = QObject::tr("Folder");
childItem->setFlags(item->flags() | Qt::ItemIsEditable);
childItem->setIcon(0, bookmarkIcon);
childItem->setText(0, title);
- childItem->setText(1, child.attribute("href"));
- } else if (child.tagName() == "separator") {
+ childItem->setText(1, child.attribute(hrefAttribute()));
+ } else if (child.tagName() == QLatin1String("separator")) {
QTreeWidgetItem *childItem = createItem(child, item);
childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable));
childItem->setText(0, QString(30, 0xB7));
@@ -191,6 +219,6 @@ QTreeWidgetItem *XbelTree::createItem(const QDomElement &element,
} else {
item = new QTreeWidgetItem(this);
}
- domElementForItem.insert(item, element);
+ item->setData(0, DomElementRole, QVariant::fromValue(element));
return item;
}
diff --git a/examples/xml/dombookmarks/xbeltree.h b/examples/xml/dombookmarks/xbeltree.h
index bf4b55ea74..f6c7ef8bfe 100644
--- a/examples/xml/dombookmarks/xbeltree.h
+++ b/examples/xml/dombookmarks/xbeltree.h
@@ -52,7 +52,6 @@
#define XBELTREE_H
#include <QDomDocument>
-#include <QHash>
#include <QIcon>
#include <QTreeWidget>
@@ -64,10 +63,15 @@ public:
XbelTree(QWidget *parent = 0);
bool read(QIODevice *device);
- bool write(QIODevice *device);
+ bool write(QIODevice *device) const;
+
+protected:
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE;
+#endif
private slots:
- void updateDomElement(QTreeWidgetItem *item, int column);
+ void updateDomElement(const QTreeWidgetItem *item, int column);
private:
void parseFolderElement(const QDomElement &element,
@@ -76,7 +80,6 @@ private:
QTreeWidgetItem *parentItem = 0);
QDomDocument domDocument;
- QHash<QTreeWidgetItem *, QDomElement> domElementForItem;
QIcon folderIcon;
QIcon bookmarkIcon;
};
diff --git a/examples/xml/saxbookmarks/mainwindow.cpp b/examples/xml/saxbookmarks/mainwindow.cpp
index 2ce2b9a508..0583cd82cf 100644
--- a/examples/xml/saxbookmarks/mainwindow.cpp
+++ b/examples/xml/saxbookmarks/mainwindow.cpp
@@ -62,17 +62,40 @@ MainWindow::MainWindow()
treeWidget = new QTreeWidget;
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
treeWidget->setHeaderLabels(labels);
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(treeWidget, &QWidget::customContextMenuRequested,
+ this, &MainWindow::onCustomContextMenuRequested);
+#endif
setCentralWidget(treeWidget);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("SAX Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const QTreeWidgetItem *item = treeWidget->itemAt(pos);
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
void MainWindow::open()
{
QString fileName =
@@ -93,8 +116,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -116,8 +139,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -134,37 +157,21 @@ void MainWindow::about()
"hand."));
}
-void MainWindow::createActions()
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
diff --git a/examples/xml/saxbookmarks/mainwindow.h b/examples/xml/saxbookmarks/mainwindow.h
index 828a0ed14e..20a11bb202 100644
--- a/examples/xml/saxbookmarks/mainwindow.h
+++ b/examples/xml/saxbookmarks/mainwindow.h
@@ -68,20 +68,13 @@ public slots:
void open();
void saveAs();
void about();
-
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void onCustomContextMenuRequested(const QPoint &pos);
+#endif
private:
- void createActions();
void createMenus();
QTreeWidget *treeWidget;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
#endif
diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp
index 30ce1428e6..ee6f113f9c 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.cpp
+++ b/examples/xml/saxbookmarks/xbelgenerator.cpp
@@ -52,7 +52,7 @@
#include "xbelgenerator.h"
-XbelGenerator::XbelGenerator(QTreeWidget *treeWidget)
+XbelGenerator::XbelGenerator(const QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
}
@@ -81,25 +81,25 @@ QString XbelGenerator::indent(int depth)
QString XbelGenerator::escapedText(const QString &str)
{
QString result = str;
- result.replace("&", "&amp;");
- result.replace("<", "&lt;");
- result.replace(">", "&gt;");
+ result.replace('&', "&amp;");
+ result.replace('<', "&lt;");
+ result.replace('>', "&gt;");
return result;
}
QString XbelGenerator::escapedAttribute(const QString &str)
{
QString result = escapedText(str);
- result.replace("\"", "&quot;");
+ result.replace(QLatin1Char('"'), "&quot;");
result.prepend(QLatin1Char('"'));
result.append(QLatin1Char('"'));
return result;
}
-void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
+void XbelGenerator::generateItem(const QTreeWidgetItem *item, int depth)
{
QString tagName = item->data(0, Qt::UserRole).toString();
- if (tagName == "folder") {
+ if (tagName == QLatin1String("folder")) {
bool folded = !treeWidget->isItemExpanded(item);
out << indent(depth) << "<folder folded=\"" << (folded ? "yes" : "no")
<< "\">\n"
@@ -110,7 +110,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
generateItem(item->child(i), depth + 1);
out << indent(depth) << "</folder>\n";
- } else if (tagName == "bookmark") {
+ } else if (tagName == QLatin1String("bookmark")) {
out << indent(depth) << "<bookmark";
if (!item->text(1).isEmpty())
out << " href=" << escapedAttribute(item->text(1));
@@ -118,7 +118,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
<< indent(depth + 1) << "<title>" << escapedText(item->text(0))
<< "</title>\n"
<< indent(depth) << "</bookmark>\n";
- } else if (tagName == "separator") {
+ } else if (tagName == QLatin1String("separator")) {
out << indent(depth) << "<separator/>\n";
}
}
diff --git a/examples/xml/saxbookmarks/xbelgenerator.h b/examples/xml/saxbookmarks/xbelgenerator.h
index 44069599e2..abfabfd75c 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.h
+++ b/examples/xml/saxbookmarks/xbelgenerator.h
@@ -61,7 +61,7 @@ QT_END_NAMESPACE
class XbelGenerator
{
public:
- XbelGenerator(QTreeWidget *treeWidget);
+ explicit XbelGenerator(const QTreeWidget *treeWidget);
bool write(QIODevice *device);
@@ -69,9 +69,9 @@ private:
static QString indent(int indentLevel);
static QString escapedText(const QString &str);
static QString escapedAttribute(const QString &str);
- void generateItem(QTreeWidgetItem *item, int depth);
+ void generateItem(const QTreeWidgetItem *item, int depth);
- QTreeWidget *treeWidget;
+ const QTreeWidget *treeWidget;
QTextStream out;
};
diff --git a/examples/xml/saxbookmarks/xbelhandler.cpp b/examples/xml/saxbookmarks/xbelhandler.cpp
index 03b16c81f1..7e2a9db3c2 100644
--- a/examples/xml/saxbookmarks/xbelhandler.cpp
+++ b/examples/xml/saxbookmarks/xbelhandler.cpp
@@ -52,6 +52,10 @@
#include "xbelhandler.h"
+static inline QString versionAttribute() { return QStringLiteral("version"); }
+static inline QString hrefAttribute() { return QStringLiteral("href"); }
+static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
XbelHandler::XbelHandler(QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
@@ -72,32 +76,32 @@ bool XbelHandler::startElement(const QString & /* namespaceURI */,
const QString &qName,
const QXmlAttributes &attributes)
{
- if (!metXbelTag && qName != "xbel") {
+ if (!metXbelTag && qName != QLatin1String("xbel")) {
errorStr = QObject::tr("The file is not an XBEL file.");
return false;
}
- if (qName == "xbel") {
- QString version = attributes.value("version");
- if (!version.isEmpty() && version != "1.0") {
+ if (qName == QLatin1String("xbel")) {
+ QString version = attributes.value(versionAttribute());
+ if (!version.isEmpty() && version != QLatin1String("1.0")) {
errorStr = QObject::tr("The file is not an XBEL version 1.0 file.");
return false;
}
metXbelTag = true;
- } else if (qName == "folder") {
+ } else if (qName == QLatin1String("folder")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, folderIcon);
item->setText(0, QObject::tr("Folder"));
- bool folded = (attributes.value("folded") != "no");
+ bool folded = (attributes.value(foldedAttribute()) != QLatin1String("no"));
treeWidget->setItemExpanded(item, !folded);
- } else if (qName == "bookmark") {
+ } else if (qName == QLatin1String("bookmark")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, bookmarkIcon);
item->setText(0, QObject::tr("Unknown title"));
- item->setText(1, attributes.value("href"));
- } else if (qName == "separator") {
+ item->setText(1, attributes.value(hrefAttribute()));
+ } else if (qName == QLatin1String("separator")) {
item = createChildItem(qName);
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
item->setText(0, QString(30, 0xB7));
@@ -111,11 +115,11 @@ bool XbelHandler::endElement(const QString & /* namespaceURI */,
const QString & /* localName */,
const QString &qName)
{
- if (qName == "title") {
+ if (qName == QLatin1String("title")) {
if (item)
item->setText(0, currentText);
- } else if (qName == "folder" || qName == "bookmark"
- || qName == "separator") {
+ } else if (qName == QLatin1String("folder") || qName == QLatin1String("bookmark")
+ || qName == QLatin1String("separator")) {
item = item->parent();
}
return true;
diff --git a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
index 0720e3eadd..ad093c2098 100644
--- a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
+++ b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
@@ -167,7 +167,7 @@
add them to the \c fileMenu and \c helpMenu. The connections are as shown
below:
- \snippet streambookmarks/mainwindow.cpp 4
+ \snippet streambookmarks/mainwindow.cpp 5
The \c createMenus() function creates the \c fileMenu and \c helpMenu
and adds the QAction objects to them in order to create the menu shown
diff --git a/examples/xml/streambookmarks/mainwindow.cpp b/examples/xml/streambookmarks/mainwindow.cpp
index 7c0fd8720d..c9a18fa3c4 100644
--- a/examples/xml/streambookmarks/mainwindow.cpp
+++ b/examples/xml/streambookmarks/mainwindow.cpp
@@ -63,18 +63,41 @@ MainWindow::MainWindow()
treeWidget = new QTreeWidget;
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
treeWidget->setHeaderLabels(labels);
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(treeWidget, &QWidget::customContextMenuRequested,
+ this, &MainWindow::onCustomContextMenuRequested);
+#endif
setCentralWidget(treeWidget);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("QXmlStream Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
//! [0]
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const QTreeWidgetItem *item = treeWidget->itemAt(pos);
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
//! [1]
void MainWindow::open()
{
@@ -92,8 +115,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -101,8 +124,8 @@ void MainWindow::open()
if (!reader.read(&file)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Parse error in file %1:\n\n%2")
- .arg(fileName)
- .arg(reader.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ reader.errorString()));
} else {
statusBar()->showMessage(tr("File loaded"), 2000);
}
@@ -124,8 +147,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -144,41 +167,23 @@ void MainWindow::about()
}
//! [3]
-//! [4]
-void MainWindow::createActions()
+//! [5]
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-//! [4]
-
-//! [5]
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
//! [5]
diff --git a/examples/xml/streambookmarks/mainwindow.h b/examples/xml/streambookmarks/mainwindow.h
index 2b6feeb26f..fbdc1e0c62 100644
--- a/examples/xml/streambookmarks/mainwindow.h
+++ b/examples/xml/streambookmarks/mainwindow.h
@@ -69,20 +69,13 @@ public slots:
void open();
void saveAs();
void about();
-
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void onCustomContextMenuRequested(const QPoint &pos);
+#endif
private:
- void createActions();
void createMenus();
QTreeWidget *treeWidget;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
//! [0]
diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp
index 53d6b94ba0..099985d91e 100644
--- a/examples/xml/streambookmarks/xbelreader.cpp
+++ b/examples/xml/streambookmarks/xbelreader.cpp
@@ -72,10 +72,12 @@ bool XbelReader::read(QIODevice *device)
xml.setDevice(device);
if (xml.readNextStartElement()) {
- if (xml.name() == "xbel" && xml.attributes().value("version") == "1.0")
+ if (xml.name() == QLatin1String("xbel")
+ && xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) {
readXBEL();
- else
+ } else {
xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
+ }
}
return !xml.error();
@@ -95,14 +97,14 @@ QString XbelReader::errorString() const
//! [3]
void XbelReader::readXBEL()
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "xbel");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel"));
while (xml.readNextStartElement()) {
- if (xml.name() == "folder")
+ if (xml.name() == QLatin1String("folder"))
readFolder(0);
- else if (xml.name() == "bookmark")
+ else if (xml.name() == QLatin1String("bookmark"))
readBookmark(0);
- else if (xml.name() == "separator")
+ else if (xml.name() == QLatin1String("separator"))
readSeparator(0);
else
xml.skipCurrentElement();
@@ -113,7 +115,7 @@ void XbelReader::readXBEL()
//! [4]
void XbelReader::readTitle(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "title");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title"));
QString title = xml.readElementText();
item->setText(0, title);
@@ -123,7 +125,7 @@ void XbelReader::readTitle(QTreeWidgetItem *item)
//! [5]
void XbelReader::readSeparator(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "separator");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator"));
QTreeWidgetItem *separator = createChildItem(item);
separator->setFlags(item->flags() & ~Qt::ItemIsSelectable);
@@ -134,20 +136,20 @@ void XbelReader::readSeparator(QTreeWidgetItem *item)
void XbelReader::readFolder(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "folder");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder"));
QTreeWidgetItem *folder = createChildItem(item);
- bool folded = (xml.attributes().value("folded") != "no");
+ bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no"));
treeWidget->setItemExpanded(folder, !folded);
while (xml.readNextStartElement()) {
- if (xml.name() == "title")
+ if (xml.name() == QLatin1String("title"))
readTitle(folder);
- else if (xml.name() == "folder")
+ else if (xml.name() == QLatin1String("folder"))
readFolder(folder);
- else if (xml.name() == "bookmark")
+ else if (xml.name() == QLatin1String("bookmark"))
readBookmark(folder);
- else if (xml.name() == "separator")
+ else if (xml.name() == QLatin1String("separator"))
readSeparator(folder);
else
xml.skipCurrentElement();
@@ -156,16 +158,16 @@ void XbelReader::readFolder(QTreeWidgetItem *item)
void XbelReader::readBookmark(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark"));
QTreeWidgetItem *bookmark = createChildItem(item);
bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable);
bookmark->setIcon(0, bookmarkIcon);
bookmark->setText(0, QObject::tr("Unknown title"));
- bookmark->setText(1, xml.attributes().value("href").toString());
+ bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString());
while (xml.readNextStartElement()) {
- if (xml.name() == "title")
+ if (xml.name() == QLatin1String("title"))
readTitle(bookmark);
else
xml.skipCurrentElement();
diff --git a/examples/xml/streambookmarks/xbelreader.h b/examples/xml/streambookmarks/xbelreader.h
index 3175441ddd..fd486a430f 100644
--- a/examples/xml/streambookmarks/xbelreader.h
+++ b/examples/xml/streambookmarks/xbelreader.h
@@ -71,6 +71,10 @@ public:
QString errorString() const;
+ static inline QString versionAttribute() { return QStringLiteral("version"); }
+ static inline QString hrefAttribute() { return QStringLiteral("href"); }
+ static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
private:
//! [2]
void readXBEL();
diff --git a/examples/xml/streambookmarks/xbelwriter.cpp b/examples/xml/streambookmarks/xbelwriter.cpp
index fdf2e1095e..2959680678 100644
--- a/examples/xml/streambookmarks/xbelwriter.cpp
+++ b/examples/xml/streambookmarks/xbelwriter.cpp
@@ -51,9 +51,14 @@
#include <QtWidgets>
#include "xbelwriter.h"
+#include "xbelreader.h"
+
+static inline QString yesValue() { return QStringLiteral("yes"); }
+static inline QString noValue() { return QStringLiteral("no"); }
+static inline QString titleElement() { return QStringLiteral("title"); }
//! [0]
-XbelWriter::XbelWriter(QTreeWidget *treeWidget)
+XbelWriter::XbelWriter(const QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
xml.setAutoFormatting(true);
@@ -66,9 +71,9 @@ bool XbelWriter::writeFile(QIODevice *device)
xml.setDevice(device);
xml.writeStartDocument();
- xml.writeDTD("<!DOCTYPE xbel>");
- xml.writeStartElement("xbel");
- xml.writeAttribute("version", "1.0");
+ xml.writeDTD(QStringLiteral("<!DOCTYPE xbel>"));
+ xml.writeStartElement(QStringLiteral("xbel"));
+ xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0"));
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
writeItem(treeWidget->topLevelItem(i));
@@ -78,24 +83,24 @@ bool XbelWriter::writeFile(QIODevice *device)
//! [1]
//! [2]
-void XbelWriter::writeItem(QTreeWidgetItem *item)
+void XbelWriter::writeItem(const QTreeWidgetItem *item)
{
QString tagName = item->data(0, Qt::UserRole).toString();
- if (tagName == "folder") {
+ if (tagName == QLatin1String("folder")) {
bool folded = !treeWidget->isItemExpanded(item);
xml.writeStartElement(tagName);
- xml.writeAttribute("folded", folded ? "yes" : "no");
- xml.writeTextElement("title", item->text(0));
+ xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue());
+ xml.writeTextElement(titleElement(), item->text(0));
for (int i = 0; i < item->childCount(); ++i)
writeItem(item->child(i));
xml.writeEndElement();
- } else if (tagName == "bookmark") {
+ } else if (tagName == QLatin1String("bookmark")) {
xml.writeStartElement(tagName);
if (!item->text(1).isEmpty())
- xml.writeAttribute("href", item->text(1));
- xml.writeTextElement("title", item->text(0));
+ xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1));
+ xml.writeTextElement(titleElement(), item->text(0));
xml.writeEndElement();
- } else if (tagName == "separator") {
+ } else if (tagName == QLatin1String("separator")) {
xml.writeEmptyElement(tagName);
}
}
diff --git a/examples/xml/streambookmarks/xbelwriter.h b/examples/xml/streambookmarks/xbelwriter.h
index b15bf60e31..465d8f0dc4 100644
--- a/examples/xml/streambookmarks/xbelwriter.h
+++ b/examples/xml/streambookmarks/xbelwriter.h
@@ -62,13 +62,13 @@ QT_END_NAMESPACE
class XbelWriter
{
public:
- XbelWriter(QTreeWidget *treeWidget);
+ explicit XbelWriter(const QTreeWidget *treeWidget);
bool writeFile(QIODevice *device);
private:
- void writeItem(QTreeWidgetItem *item);
+ void writeItem(const QTreeWidgetItem *item);
QXmlStreamWriter xml;
- QTreeWidget *treeWidget;
+ const QTreeWidget *treeWidget;
};
//! [0]
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
index 9ddebae506..ca5697dd90 100644
--- a/mkspecs/common/gcc-base.conf
+++ b/mkspecs/common/gcc-base.conf
@@ -97,6 +97,8 @@ QMAKE_CFLAGS_AVX512BW += -mavx512bw
QMAKE_CFLAGS_AVX512VL += -mavx512vl
QMAKE_CFLAGS_AVX512IFMA += -mavx512ifma
QMAKE_CFLAGS_AVX512VBMI += -mavx512vbmi
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CFLAGS_NEON += -mfpu=neon
QMAKE_CFLAGS_MIPS_DSP += -mdsp
QMAKE_CFLAGS_MIPS_DSPR2 += -mdspr2
diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf
index 13916a5646..5e2b5b59eb 100644
--- a/mkspecs/common/linux.conf
+++ b/mkspecs/common/linux.conf
@@ -35,6 +35,7 @@ QMAKE_LIBS_OPENGL = -lGL
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
QMAKE_LIBS_OPENVG = -lOpenVG
QMAKE_LIBS_THREAD = -lpthread
+QMAKE_LIBS_VULKAN =
QMAKE_INCDIR_WAYLAND =
QMAKE_LIBS_WAYLAND_CLIENT = -lwayland-client
diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf
index 02b8441547..bd9098d7f1 100644
--- a/mkspecs/common/msvc-desktop.conf
+++ b/mkspecs/common/msvc-desktop.conf
@@ -44,6 +44,8 @@ QMAKE_CFLAGS_SSE3 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSSE3 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSE4_1 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSE4_2 = $$QMAKE_CFLAGS_SSE2
+QMAKE_CFLAGS_AESNI = $$QMAKE_CFLAGS_SSE2
+QMAKE_CFLAGS_SHANI = $$QMAKE_CFLAGS_SSE2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
@@ -104,3 +106,4 @@ VCSOLUTION_EXTENSION = .sln
VCPROJ_KEYWORD = Qt4VSv1.0
include(windows-gles.conf)
+include(windows-vulkan.conf)
diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf
index 4ef03d8587..77e0476777 100644
--- a/mkspecs/common/qcc-base.conf
+++ b/mkspecs/common/qcc-base.conf
@@ -33,6 +33,8 @@ QMAKE_CFLAGS_SSE4_1 += -msse4.1
QMAKE_CFLAGS_SSE4_2 += -msse4.2
QMAKE_CFLAGS_AVX += -mavx
QMAKE_CFLAGS_AVX2 += -mavx2
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -lang-c++
QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS
diff --git a/mkspecs/common/windows-vulkan.conf b/mkspecs/common/windows-vulkan.conf
new file mode 100644
index 0000000000..c928a8f315
--- /dev/null
+++ b/mkspecs/common/windows-vulkan.conf
@@ -0,0 +1,5 @@
+# Pick up the VULKAN_SDK env var set by the LunarG SDK so that the Vulkan
+# headers are found out-of-the-box on typical Windows setups.
+
+QMAKE_INCDIR_VULKAN = $(VULKAN_SDK)\\include
+QMAKE_LIBS_VULKAN =
diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf
index 818264c46b..1b9bf4d20f 100644
--- a/mkspecs/common/winrt_winphone/qmake.conf
+++ b/mkspecs/common/winrt_winphone/qmake.conf
@@ -34,6 +34,8 @@ QMAKE_CFLAGS_SSE4_1 = -arch:SSE2
QMAKE_CFLAGS_SSE4_2 = -arch:SSE2
QMAKE_CFLAGS_AVX = -arch:AVX
QMAKE_CFLAGS_AVX2 = -arch:AVX
+QMAKE_CFLAGS_AESNI = -arch:SSE2
+QMAKE_CFLAGS_SHANI = -arch:SSE2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf
index 648723d6ff..9248be2d68 100644
--- a/mkspecs/features/qt_module_headers.prf
+++ b/mkspecs/features/qt_module_headers.prf
@@ -121,18 +121,19 @@ exists($$OUT_PWD/qt$${MODULE}-config.h) {
for (injection, SYNCQT.INJECTIONS) {
injects = $$split(injection, :)
dst_hdr = $$absolute_path($$member(injects, 0), $$MODULE_INC_OUTDIR)
- fwd_hdr = $$member(injects, 1)
+ ofwd_hdr = $$member(injects, 1)
+ fwd_hdr = $$replace(ofwd_hdr, ^\\^, )
MAIN_FWD = $$MODULE_INC_OUTDIR/$$fwd_hdr
MAIN_FWD_CONT = '$${LITERAL_HASH}include "$$relative_path($$dst_hdr, $$dirname(MAIN_FWD))"'
write_file($$MAIN_FWD, MAIN_FWD_CONT)|error()
- touch($$MAIN_FWD, $$dst_hdr)
+ equals(fwd_hdr, ofwd_hdr): touch($$MAIN_FWD, $$dst_hdr)
!git_build: QMAKE_DISTCLEAN += $$MAIN_FWD
injects = $$member(injects, 2, -1)
for (inject, injects) {
CLASS_FWD = $$MODULE_INC_OUTDIR/$$inject
CLASS_FWD_CONT = '$${LITERAL_HASH}include "$$fwd_hdr"'
write_file($$CLASS_FWD, CLASS_FWD_CONT)|error()
- touch($$CLASS_FWD, $$dst_hdr)
+ touch($$CLASS_FWD, $$MAIN_FWD)
!git_build: QMAKE_DISTCLEAN += $$CLASS_FWD
}
}
@@ -245,7 +246,7 @@ headersclean:!internal_module {
}
hcleanCOMMAND = $$QMAKE_CXX -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -xc++ ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
- } else: win32-msvc2013 {
+ } else: msvc:!intel_icl {
# 4180: qualifier applied to function type has no meaning; ignored
# 4458: declaration of 'identifier' hides class member
# -Za enables strict standards behavior, but we can't add it because
diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf
index 953fc52c65..aca9ae6243 100644
--- a/mkspecs/features/simd.prf
+++ b/mkspecs/features/simd.prf
@@ -93,6 +93,8 @@ addSimdCompiler(sse3)
addSimdCompiler(ssse3)
addSimdCompiler(sse4_1)
addSimdCompiler(sse4_2)
+addSimdCompiler(aesni)
+addSimdCompiler(shani)
addSimdCompiler(avx)
addSimdCompiler(avx2)
addSimdCompiler(avx512f)
diff --git a/mkspecs/linux-icc-k1om/qmake.conf b/mkspecs/linux-icc-k1om/qmake.conf
new file mode 100644
index 0000000000..86cd921e89
--- /dev/null
+++ b/mkspecs/linux-icc-k1om/qmake.conf
@@ -0,0 +1,21 @@
+#
+# qmake configuration for linux-icc-k1om
+#
+# Written for Intel C++ Compiler
+#
+# This mkspec is intended for use on x100 Co-processors
+#
+
+# Use the linux-icc as the base for our configuration
+include(../linux-icc/qmake.conf)
+
+QMAKE_CC = icc -mmic
+QMAKE_CFLAGS_WARN_ON += -wd10364,1786
+
+QMAKE_CXX = icpc -mmic
+QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
+
+QMAKE_LFLAGS += -mmic
+QMAKE_LFLAGS_APP =
+QMAKE_AR = xiar crs
+
diff --git a/mkspecs/linux-icc-k1om/qplatformdefs.h b/mkspecs/linux-icc-k1om/qplatformdefs.h
new file mode 100644
index 0000000000..33a3bf0e1c
--- /dev/null
+++ b/mkspecs/linux-icc-k1om/qplatformdefs.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "../linux-icc/qplatformdefs.h"
diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf
index 196e33432c..801a8acf6a 100644
--- a/mkspecs/linux-icc/qmake.conf
+++ b/mkspecs/linux-icc/qmake.conf
@@ -42,6 +42,8 @@ QMAKE_CFLAGS_AVX512PF += -xMIC-AVX512
QMAKE_CFLAGS_AVX512DQ += -xCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -xCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -xCORE-AVX512
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CXX = icpc
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf
index bb454377ef..bb9a495f6f 100644
--- a/mkspecs/macx-icc/qmake.conf
+++ b/mkspecs/macx-icc/qmake.conf
@@ -40,6 +40,8 @@ QMAKE_CFLAGS_AVX512PF += -xMIC-AVX512
QMAKE_CFLAGS_AVX512DQ += -xCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -xCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -xCORE-AVX512
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CXX = icpc
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf
index d6b08f5323..224c81fb4a 100644
--- a/mkspecs/win32-g++/qmake.conf
+++ b/mkspecs/win32-g++/qmake.conf
@@ -28,6 +28,8 @@ QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS += -fno-keep-inline-dllexport
QMAKE_CFLAGS_WARN_ON += -Wextra
QMAKE_CFLAGS_SSE2 += -mstackrealign
+QMAKE_CFLAGS_AESNI = -maes
+QMAKE_CFLAGS_SHANI = -msha
QMAKE_CXX = $${CROSS_COMPILE}g++
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
@@ -78,6 +80,7 @@ QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
include(../common/windows-gles.conf)
+include(../common/windows-vulkan.conf)
include(../common/gcc-base.conf)
load(qt_config)
diff --git a/mkspecs/win32-icc-k1om/qmake.conf b/mkspecs/win32-icc-k1om/qmake.conf
new file mode 100644
index 0000000000..498b47cf2d
--- /dev/null
+++ b/mkspecs/win32-icc-k1om/qmake.conf
@@ -0,0 +1,15 @@
+#
+# qmake configuration for win32-icc-k1om
+#
+# Written for Intel C++
+#
+# Use the win32-icc as the base for our configuration
+include(../win32-icc/qmake.conf)
+
+# rework k1om
+
+QMAKE_CC = icl /Qmic
+QMAKE_CXX = icl /Qmic
+QMAKE_LINK = xild
+QMAKE_LINK_SHLIB = xild
+QMAKE_LFLAGS = -limf -lsvml -lirng -lintlc
diff --git a/mkspecs/win32-icc-k1om/qplatformdefs.h b/mkspecs/win32-icc-k1om/qplatformdefs.h
new file mode 100644
index 0000000000..8a3afa7630
--- /dev/null
+++ b/mkspecs/win32-icc-k1om/qplatformdefs.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "../win32-msvc/qplatformdefs.h"
diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf
index 6e2589b4c4..171145690e 100644
--- a/mkspecs/win32-icc/qmake.conf
+++ b/mkspecs/win32-icc/qmake.conf
@@ -33,6 +33,8 @@ QMAKE_CFLAGS_AVX512PF += -QxMIC-AVX512
QMAKE_CFLAGS_AVX512DQ += -QxCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -QxCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -QxCORE-AVX512
+QMAKE_CFLAGS_AESNI = -QxSSE2
+QMAKE_CFLAGS_SHANI = -QxSSE4.2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS /Zc:forScope
@@ -57,5 +59,6 @@ QMAKE_LIB = xilib /NOLOGO
DSP_EXTENSION = .dsp
include(../common/windows-gles.conf)
+include(../common/windows-vulkan.conf)
load(qt_config)
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index ed1668d54e..768cc0248e 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -2,107 +2,143 @@ QMKSRC = $(SOURCE_PATH)/qmake
QMKLIBSRC = $(QMKSRC)/library
QMKGENSRC = $(QMKSRC)/generators
-#qmake code
-OBJS=project.o option.o property.o main.o ioutils.o proitems.o \
- qmakevfs.o qmakeglobals.o qmakeparser.o qmakeevaluator.o qmakebuiltins.o \
- makefile.o unixmake2.o unixmake.o \
- mingw_make.o winmakefile.o projectgenerator.o \
- meta.o makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
- msvc_vcproj.o msvc_vcxproj.o msvc_nmake.o msvc_objectmodel.o msbuild_objectmodel.o
-
-#qt code
-QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \
- qringbuffer.o qdebug.o qmalloc.o qglobal.o \
- qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \
- qfilesystementry.o qfilesystemengine.o qfsfileengine.o qfsfileengine_iterator.o qregexp.o \
- qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \
- qabstractfileengine.o qtemporaryfile.o qmap.o qmetatype.o qsettings.o qsystemerror.o \
- qvariant.o qvsnprintf.o qlocale.o qlocale_tools.o qlinkedlist.o qnumeric.o \
- qcryptographichash.o qxmlstream.o qxmlutils.o qlogging.o qoperatingsystemversion.o \
- qjson.o qjsondocument.o qjsonparser.o qjsonarray.o qjsonobject.o qjsonvalue.o \
- $(QTOBJS) $(QTOBJS2)
-
-
-#all sources, used for the depend target
+#qmake code (please keep in order matching DEPEND_SRC)
+OBJS = \
+ main.o meta.o option.o project.o property.o \
+ ioutils.o proitems.o qmakebuiltins.o qmakeevaluator.o \
+ qmakeglobals.o qmakeparser.o qmakevfs.o \
+ pbuilder_pbx.o \
+ makefile.o makefiledeps.o metamakefile.o projectgenerator.o \
+ unixmake2.o unixmake.o \
+ mingw_make.o msbuild_objectmodel.o \
+ msvc_nmake.o msvc_objectmodel.o msvc_vcproj.o msvc_vcxproj.o \
+ winmakefile.o \
+ xmloutput.o
+
+#qt code (please keep in order matching DEPEND_SRC)
+QOBJS = \
+ qtextcodec.o qutfcodec.o \
+ qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o \
+ qabstractfileengine.o qbuffer.o qdatastream.o qdebug.o \
+ qdir.o qdiriterator.o \
+ qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \
+ qfilesystementry.o qfsfileengine.o qfsfileengine_iterator.o \
+ qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o \
+ qjsonarray.o qjson.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \
+ qmetatype.o qsystemerror.o qvariant.o \
+ quuid.o \
+ qarraydata.o qbitarray.o qbytearray.o qbytearraymatcher.o \
+ qcryptographichash.o qdatetime.o qhash.o qlinkedlist.o qlist.o \
+ qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \
+ qstringbuilder.o qstring_compat.o qstring.o qstringlist.o qversionnumber.o \
+ qvsnprintf.o qxmlstream.o qxmlutils.o \
+ $(QTOBJS) $(QTOBJS2)
+# QTOBJS and QTOBJS2 are populated by Makefile.unix.* as for QTSRC (see below).
+# Note: qlibraryinfo.o omitted deliberately - see below.
+# Note: qcore_mac_objc.o is in SOURCES (see qmake.pri) but not QOBJS.
+
+#all sources, used for the depend target (please keep alphabetic in each block)
DEPEND_SRC = \
- $(QMKSRC)/main.cpp $(QMKSRC)/project.cpp $(QMKSRC)/option.cpp $(QMKSRC)/property.cpp \
+ $(QMKSRC)/main.cpp \
$(QMKSRC)/meta.cpp \
- $(QMKLIBSRC)/ioutils.cpp $(QMKLIBSRC)/proitems.cpp $(QMKLIBSRC)/qmakeglobals.cpp \
- $(QMKLIBSRC)/qmakeparser.cpp $(QMKLIBSRC)/qmakeevaluator.cpp $(QMKLIBSRC)/qmakebuiltins.cpp \
- $(QMKGENSRC)/makefiledeps.cpp $(QMKGENSRC)/metamakefile.cpp \
- $(QMKGENSRC)/projectgenerator.cpp $(QMKGENSRC)/makefile.cpp \
- $(QMKGENSRC)/unix/unixmake.cpp $(QMKGENSRC)/unix/unixmake2.cpp \
+ $(QMKSRC)/option.cpp \
+ $(QMKSRC)/project.cpp \
+ $(QMKSRC)/property.cpp \
+ $(QMKLIBSRC)/ioutils.cpp \
+ $(QMKLIBSRC)/proitems.cpp \
+ $(QMKLIBSRC)/qmakebuiltins.cpp \
+ $(QMKLIBSRC)/qmakeevaluator.cpp \
+ $(QMKLIBSRC)/qmakeglobals.cpp \
+ $(QMKLIBSRC)/qmakeparser.cpp \
+ $(QMKLIBSRC)/qmakevfs.cpp \
$(QMKGENSRC)/mac/pbuilder_pbx.cpp \
- $(QMKGENSRC)/win32/registry.cpp \
+ $(QMKGENSRC)/makefile.cpp \
+ $(QMKGENSRC)/makefiledeps.cpp \
+ $(QMKGENSRC)/metamakefile.cpp \
+ $(QMKGENSRC)/projectgenerator.cpp \
+ $(QMKGENSRC)/unix/unixmake2.cpp \
+ $(QMKGENSRC)/unix/unixmake.cpp \
+ $(QMKGENSRC)/win32/mingw_make.cpp \
+ $(QMKGENSRC)/win32/msbuild_objectmodel.cpp \
+ $(QMKGENSRC)/win32/msvc_nmake.cpp \
+ $(QMKGENSRC)/win32/msvc_objectmodel.cpp \
+ $(QMKGENSRC)/win32/msvc_vcproj.cpp \
+ $(QMKGENSRC)/win32/msvc_vcxproj.cpp \
$(QMKGENSRC)/win32/winmakefile.cpp \
- $(QMKGENSRC)/win32/mingw_make.cpp $(QMKGENSRC)/win32/msvc_nmake.cpp \
- $(QMKGENSRC)/mac/xmloutput.cpp \
- $(QMKGENSRC)/win32/msvc_vcproj.cpp $(QMKGENSRC)/win32/msvc_vcxproj.cpp \
- $(QMKGENSRC)/win32/msvc_objectmodel.cpp $(QMKGENSRC)/win32/msbuild_objectmodel.cpp \
- $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
- $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
+ $(QMKGENSRC)/xmloutput.cpp \
+ $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp \
+ $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qglobal.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
- $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
- $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp \
$(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdir.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfile.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp \
$(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qsettings.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjson.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \
+ $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \
+ $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \
+ $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
+ $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
+ $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \
$(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdir.cpp $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
+ $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qhash.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qhash.cpp $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp \
- $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \
- $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm \
- $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \
- $(SOURCE_PATH)/src/corelib/io/qsettings.cpp $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
- $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstring.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp \
$(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \
$(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \
- $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
- $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
- $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjson.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \
$(QTSRCS) $(QTSRCS2)
+# QTSRCS and QTSRCS2 come from Makefile.unix.* (concatenated with this
+# by configure); QTSRCS2 may include *.mm entries on macOS.
+# See below for special handling of qlibraryinfo.cpp
CPPFLAGS = -g $(EXTRA_CPPFLAGS) \
- -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKSRC)/generators -I$(QMKSRC)/generators/unix -I$(QMKSRC)/generators/win32 \
- -I$(QMKSRC)/generators/mac \
+ -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKGENSRC) \
+ -I$(QMKGENSRC)/unix -I$(QMKGENSRC)/win32 -I$(QMKGENSRC)/mac \
-I$(INC_PATH) -I$(INC_PATH)/QtCore \
-I$(INC_PATH)/QtCore/$(QT_VERSION) -I$(INC_PATH)/QtCore/$(QT_VERSION)/QtCore \
-I$(BUILD_PATH)/src/corelib/global \
-I$(QMAKESPEC) \
-DQT_VERSION_STR=\"$(QT_VERSION)\" -DQT_VERSION_MAJOR=$(QT_MAJOR_VERSION) -DQT_VERSION_MINOR=$(QT_MINOR_VERSION) -DQT_VERSION_PATCH=$(QT_PATCH_VERSION) \
- -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
- -DQT_NO_FOREACH
+ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
+ -DQT_NO_FOREACH
CXXFLAGS = $(EXTRA_CXXFLAGS) $(CONFIG_CXXFLAGS) $(CPPFLAGS)
LFLAGS = $(EXTRA_LFLAGS) $(CONFIG_LFLAGS)
@@ -220,222 +256,225 @@ projectgenerator.o: $(QMKSRC)/generators/projectgenerator.cpp
qtextstream.o: $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) -DQT_BUILD_QMAKE_BOOTSTRAP $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) -DQT_BUILD_QMAKE_BOOTSTRAP $<
qlibraryinfo_final.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(BUILD_PATH)/src/corelib/global/qconfig.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsettings_mac.o: $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qringbuffer.o: $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qvsnprintf.o: $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qcore_mac.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qoperatingsystemversion.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qoperatingsystemversion_win.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qoperatingsystemversion_darwin.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qcore_mac_objc.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qcore_foundation.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qtextcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstring_compat.o: $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstringbuilder.o: $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale_tools.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale_unix.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
+
+qversionnumber.o: $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfiledevice.o: $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemiterator_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine_iterator.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qregexp.o: $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbitarray.o: $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdir.o: $(SOURCE_PATH)/src/corelib/io/qdir.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdir.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdiriterator.o: $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qhash.o: $(SOURCE_PATH)/src/corelib/tools/qhash.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qhash.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
-qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
+qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjson.o: $(SOURCE_PATH)/src/corelib/json/qjson.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjson.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsondocument.o: $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonparser.o: $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonarray.o: $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonobject.o: $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonvalue.o: $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
# DO NOT DELETE THIS LINE -- make depend depends on it
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 7639d09ffd..f62b4cfeba 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -93,6 +93,7 @@ QTOBJS= \
qlocale.obj \
qlocale_tools.obj \
qlocale_win.obj \
+ qversionnumber.obj \
qmalloc.obj \
qmap.obj \
qoperatingsystemversion.obj \
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index d8ab7d096d..ceb93fde2d 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -3514,6 +3514,20 @@
\snippet code/doc_src_qmake-manual.pro 169
+ \section2 versionAtLeast(variablename, versionNumber)
+
+ Tests that the version number from \c variablename is greater than or equal
+ to \c versionNumber. The version number is considered to be a sequence of
+ non-negative decimal numbers delimited by '.'; any non-numerical tail of
+ the string will be ignored. Comparison is performed segment-wise from left
+ to right; if one version is a prefix of the other, it is considered smaller.
+
+ \section2 versionAtMost(variablename, versionNumber)
+
+ Tests that the version number from \c variablename is less than or equal to
+ \c versionNumber. Works as
+ \l{versionAtLeast(variablename, versionNumber)}{versionAtLeast()}.
+
\section2 warning(string)
Always succeeds, and displays \c string as a warning message to the user.
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index 461f46e705..31b3ae6825 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -51,6 +51,7 @@
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qthreadpool.h>
#endif
+#include <qversionnumber.h>
#include <algorithm>
@@ -99,6 +100,7 @@ enum ExpandFunc {
enum TestFunc {
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
+ T_VERSION_AT_LEAST, T_VERSION_AT_MOST,
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE,
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
@@ -172,6 +174,8 @@ void QMakeEvaluator::initFunctionStatics()
{ "lessThan", T_LESSTHAN },
{ "equals", T_EQUALS },
{ "isEqual", T_EQUALS },
+ { "versionAtLeast", T_VERSION_AT_LEAST },
+ { "versionAtMost", T_VERSION_AT_MOST },
{ "exists", T_EXISTS },
{ "export", T_EXPORT },
{ "clear", T_CLEAR },
@@ -1557,6 +1561,19 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
return returnBool(values(map(args.at(0))).join(statics.field_sep)
== args.at(1).toQString(m_tmp1));
+ case T_VERSION_AT_LEAST:
+ case T_VERSION_AT_MOST: {
+ if (args.count() != 2) {
+ evalError(fL1S("%1(variable, versionNumber) requires two arguments.")
+ .arg(function.toQString(m_tmp1)));
+ return ReturnFalse;
+ }
+ const QVersionNumber lvn = QVersionNumber::fromString(values(args.at(0).toKey()).join('.'));
+ const QVersionNumber rvn = QVersionNumber::fromString(args.at(1).toQString());
+ if (func_t == T_VERSION_AT_LEAST)
+ return returnBool(lvn >= rvn);
+ return returnBool(lvn <= rvn);
+ }
case T_CLEAR: {
if (args.count() != 1) {
evalError(fL1S("%1(variable) requires one argument.")
diff --git a/qmake/qmake.pri b/qmake/qmake.pri
index c0f7250bcf..77c190bb9a 100644
--- a/qmake/qmake.pri
+++ b/qmake/qmake.pri
@@ -68,6 +68,7 @@ bootstrap { #Qt code
qlibraryinfo.cpp \
qsystemerror.cpp \
qvariant.cpp \
+ qversionnumber.cpp \
qvsnprintf.cpp \
qxmlstream.cpp \
qxmlutils.cpp \
@@ -119,6 +120,7 @@ bootstrap { #Qt code
qtextstream.h \
quuid.h \
qvector.h \
+ qversionnumber.h \
qxmlstream.h \
qxmlutils.h \
qjson.h \
@@ -132,8 +134,7 @@ bootstrap { #Qt code
unix {
SOURCES += qfilesystemengine_unix.cpp qfilesystemiterator_unix.cpp qfsfileengine_unix.cpp
mac {
- SOURCES += qcore_mac.cpp qsettings_mac.cpp
- OBJECTIVE_SOURCES += qcore_mac_objc.mm qlocale_mac.mm
+ SOURCES += qcore_mac.cpp qsettings_mac.cpp qcore_mac_objc.mm qlocale_mac.mm
LIBS += -framework ApplicationServices -framework CoreServices -framework Foundation
} else {
SOURCES += qlocale_unix.cpp
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index e0878f078f..7c11b5d136 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -62,6 +62,9 @@ import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyCharacterMap;
@@ -1020,10 +1023,36 @@ public class QtActivityDelegate
public void hideSplashScreen()
{
+ hideSplashScreen(0);
+ }
+
+ public void hideSplashScreen(final int duration)
+ {
if (m_splashScreen == null)
return;
- m_layout.removeView(m_splashScreen);
- m_splashScreen = null;
+
+ if (duration <= 0) {
+ m_layout.removeView(m_splashScreen);
+ m_splashScreen = null;
+ return;
+ }
+
+ final Animation fadeOut = new AlphaAnimation(1, 0);
+ fadeOut.setInterpolator(new AccelerateInterpolator());
+ fadeOut.setDuration(duration);
+
+ fadeOut.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationEnd(Animation animation) { hideSplashScreen(0); }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {}
+
+ @Override
+ public void onAnimationStart(Animation animation) {}
+ });
+
+ m_splashScreen.startAnimation(fadeOut);
}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index b6dbd82597..94a2363594 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -764,13 +764,13 @@ public class QtNative
});
}
- private static void hideSplashScreen()
+ private static void hideSplashScreen(final int duration)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
- m_activityDelegate.hideSplashScreen();
+ m_activityDelegate.hideSplashScreen(duration);
}
});
}
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
index 39b03f5ff3..e91c41b305 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
@@ -49,6 +49,7 @@
****************************************************************************/
#include <QtGui>
+#include <QtWidgets>
#include "buttonwidget.h"
@@ -74,3 +75,18 @@ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
setLayout(gridLayout);
}
//! [2]
+
+//! [3]
+ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
+ : QWidget(parent)
+{
+ QGridLayout *gridLayout = new QGridLayout;
+ for (int i = 0; i < texts.size(); ++i) {
+ QString text = texts[i];
+ QPushButton *button = new QPushButton(text);
+ connect(button, &QPushButton::clicked, [=] { clicked(text); });
+ gridLayout->addWidget(button, i / 3, i % 3);
+ }
+ setLayout(gridLayout);
+}
+//! [3]
diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
index ed61511c62..6d3064d217 100644
--- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
+++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
@@ -395,24 +395,12 @@
signal, Qt provides the QObject::sender() function, which returns
a pointer to the object that sent the signal.
- The QSignalMapper class is provided for situations where many
- signals are connected to the same slot and the slot needs to
- handle each signal differently.
+ Lambda expressions are a convenient way to pass custom arguments to a slot:
- Suppose you have three push buttons that determine which file you
- will open: "Tax File", "Accounts File", or "Report File".
-
- In order to open the correct file, you use QSignalMapper::setMapping() to
- map all the QPushButton::clicked() signals to a QSignalMapper object. Then you connect
- the file's QPushButton::clicked() signal to the QSignalMapper::map() slot.
-
- \snippet signalmapper/filereader.cpp 0
-
- Then, you connect the \l{QSignalMapper::}{mapped()} signal to
- \c{readFile()} where a different file will be opened, depending on
- which push button is pressed.
-
- \snippet signalmapper/filereader.cpp 1
+ \code
+ connect(action, &QAction::triggered, engine,
+ [=]() { engine->processAction(action->text()); });
+ \endcode
\sa {Meta-Object System}, {Qt's Property System}
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 6dba733fb4..871810e5a3 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -4419,8 +4419,11 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
stderr. Under Windows, the message is sent to the debugger.
On QNX the message is sent to slogger2. This
function does nothing if \c QT_NO_WARNING_OUTPUT was defined
- during compilation; it exits if the environment variable \c
- QT_FATAL_WARNINGS is not empty.
+ during compilation; it exits if at the nth warning corresponding to the
+ counter in environment variable \c QT_FATAL_WARNINGS. That is, if the
+ environment variable contains the value 1, it will exit on the 1st message;
+ if it contains the value 10, it will exit on the 10th message. Any
+ non-numeric value is equivalent to 1.
This function takes a format string and a list of arguments,
similar to the C printf() function. The format should be a Latin-1
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 9ac29acd16..12220e10b5 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -612,6 +612,18 @@ private:
void *pool;
};
+#else
+
+#define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) (0)
+#define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) (0)
+#define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) (0)
+#define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) (0)
+#define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) (0)
+#define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) (0)
+
+#define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) (0)
+#define QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(osx) (0)
+
#endif // Q_OS_DARWIN
/*
@@ -704,9 +716,9 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line)
#if !defined(Q_ASSERT)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT(cond) do { } while ((false) && (cond))
+# define Q_ASSERT(cond) static_cast<void>(false && (cond))
# else
-# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
+# define Q_ASSERT(cond) ((cond) ? static_cast<void>(0) : qt_assert(#cond, __FILE__, __LINE__))
# endif
#endif
@@ -721,9 +733,9 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
#if !defined(Q_ASSERT_X)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT_X(cond, where, what) do { } while ((false) && (cond))
+# define Q_ASSERT_X(cond, where, what) static_cast<void>(false && (cond))
# else
-# define Q_ASSERT_X(cond, where, what) ((!(cond)) ? qt_assert_x(where, what,__FILE__,__LINE__) : qt_noop())
+# define Q_ASSERT_X(cond, where, what) ((cond) ? static_cast<void>(0) : qt_assert_x(where, what, __FILE__, __LINE__))
# endif
#endif
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 6573e0a53e..927c1bb76b 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -153,19 +153,39 @@ Q_NORETURN
static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message);
static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message);
+static int checked_var_value(const char *varname)
+{
+ // qEnvironmentVariableIntValue returns 0 on both parsing failure and on
+ // empty, but we need to distinguish between the two for backwards
+ // compatibility reasons.
+ QByteArray str = qgetenv(varname);
+ if (str.isEmpty())
+ return 0;
+
+ bool ok;
+ int value = str.toInt(&ok, 0);
+ return ok ? value : 1;
+}
+
static bool isFatal(QtMsgType msgType)
{
if (msgType == QtFatalMsg)
return true;
if (msgType == QtCriticalMsg) {
- static bool fatalCriticals = !qEnvironmentVariableIsEmpty("QT_FATAL_CRITICALS");
- return fatalCriticals;
+ static QAtomicInt fatalCriticals = checked_var_value("QT_FATAL_CRITICALS");
+
+ // it's fatal if the current value is exactly 1,
+ // otherwise decrement if it's non-zero
+ return fatalCriticals.load() && fatalCriticals.fetchAndAddRelaxed(-1) == 1;
}
if (msgType == QtWarningMsg || msgType == QtCriticalMsg) {
- static bool fatalWarnings = !qEnvironmentVariableIsEmpty("QT_FATAL_WARNINGS");
- return fatalWarnings;
+ static QAtomicInt fatalWarnings = checked_var_value("QT_FATAL_WARNINGS");
+
+ // it's fatal if the current value is exactly 1,
+ // otherwise decrement if it's non-zero
+ return fatalWarnings.load() && fatalWarnings.fetchAndAddRelaxed(-1) == 1;
}
return false;
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index da44c01594..dbc8b368b3 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -508,6 +508,7 @@ public:
AA_CompressHighFrequencyEvents = 25,
AA_DontCheckOpenGLContextThreadAffinity = 26,
AA_DisableShaderDiskCache = 27,
+ AA_DontShowShortcutsInContextMenus = 28,
// Add new attributes before this line
AA_AttributeCount
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 404bbfe65a..cd60774ee6 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -114,6 +114,11 @@
\macos menubar \e{may not} pick up a change in this attribute. Changes
in the QAction::iconVisibleInMenu property will always be picked up.
+ \value AA_DontShowShortcutsInContextMenus Actions with the Shortcut property
+ won't be shown in any shortcut menus unless specifically set by the
+ QAction::shortcutVisibleInContextMenu property. This value has
+ been added in Qt 5.10.
+
\value AA_NativeWindows Ensures that widgets have native windows.
\value AA_DontCreateNativeWidgetSiblings Ensures that siblings of native
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 7031021e16..4f79c48c51 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -311,14 +311,11 @@ Q_DECLARE_TYPEINFO(qint64, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(quint64, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(float, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(double, Q_PRIMITIVE_TYPE);
-#ifndef Q_OS_DARWIN
-Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
-#endif
-
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
// ### Qt 6: remove the other branch
// This was required so that QList<T> for these types allocates out of the array storage
+Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
# ifdef Q_COMPILER_UNICODE_STRINGS
Q_DECLARE_TYPEINFO(char16_t, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE);
@@ -327,6 +324,11 @@ Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(wchar_t, Q_PRIMITIVE_TYPE);
# endif
#else
+# ifndef Q_OS_DARWIN
+Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
+# else
+Q_DECLARE_TYPEINFO(long double, Q_RELOCATABLE_TYPE);
+# endif
# ifdef Q_COMPILER_UNICODE_STRINGS
Q_DECLARE_TYPEINFO(char16_t, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(char32_t, Q_RELOCATABLE_TYPE);
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 9606ec68e9..5f1f7e381e 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -832,6 +832,19 @@ bool QAbstractFileEngine::unmap(uchar *address)
}
/*!
+ \since 5.10
+
+ Copies the contents from the file specified by \a sourceHandle to this file
+ by cloning it.
+ Returns \c true on success; otherwise, \c false is returned.
+ */
+bool QAbstractFileEngine::clone(int sourceHandle)
+{
+ Q_UNUSED(sourceHandle);
+ return false;
+}
+
+/*!
\since 4.3
\class QAbstractFileEngineIterator
\inmodule QtCore
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index 48b3dec324..dbf0d77b15 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -147,6 +147,7 @@ public:
virtual QDateTime fileTime(FileTime time) const;
virtual void setFileName(const QString &file);
virtual int handle() const;
+ virtual bool clone(int sourceHandle);
bool atEnd() const;
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr);
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index 2369fe4726..58e2500057 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -562,6 +562,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_7 Same as Qt_5_6
\value Qt_5_8 Same as Qt_5_6
\value Qt_5_9 Same as Qt_5_6
+ \value Qt_5_10 Same as Qt_5_6
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index db1bbfbd63..993a20fcd3 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -96,10 +96,11 @@ public:
Qt_5_7 = Qt_5_6,
Qt_5_8 = Qt_5_7,
Qt_5_9 = Qt_5_8,
-#if QT_VERSION >= 0x050a00
+ Qt_5_10 = Qt_5_9,
+#if QT_VERSION >= 0x050b00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_9
+ Qt_DefaultCompiledVersion = Qt_5_10
};
enum ByteOrder {
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index be33ec2d23..341400fd93 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -648,6 +648,21 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \since 5.10
+ \fn QDebug &QDebug::operator<<(QStringView s)
+
+ Writes the string view, \a s, to the stream and returns a reference to the
+ stream. Normally, QDebug prints the string inside quotes and transforms
+ non-printable characters to their Unicode values (\\u1234).
+
+ To print non-printable characters without transformation, enable the
+ noquote() functionality. Note that some QDebug backends might not be 8-bit
+ clean.
+
+ See the QString overload for examples.
+*/
+
+/*!
\fn QDebug &QDebug::operator<<(QLatin1String s)
Writes the string, \a s, to the stream and returns a reference to the
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 61059dd694..d5f32a6efd 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -151,8 +151,11 @@ public:
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
+#if QT_STRINGVIEW_LEVEL < 2
inline QDebug &operator<<(const QString & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
inline QDebug &operator<<(const QStringRef & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
+#endif
+ inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
inline QDebug &operator<<(QLatin1String t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 41fae69bb2..6249d54f7d 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -42,6 +42,7 @@
#include "qfile.h"
#include "qfsfileengine_p.h"
#include "qtemporaryfile.h"
+#include "qtemporaryfile_p.h"
#include "qlist.h"
#include "qfileinfo.h"
#include "private/qiodevice_p.h"
@@ -790,25 +791,27 @@ QFile::copy(const QString &newName)
close();
d->setError(QFile::CopyError, tr("Cannot open for output"));
} else {
- char block[4096];
- qint64 totalRead = 0;
- while(!atEnd()) {
- qint64 in = read(block, sizeof(block));
- if (in <= 0)
- break;
- totalRead += in;
- if(in != out.write(block, in)) {
- close();
- d->setError(QFile::CopyError, tr("Failure to write block"));
- error = true;
- break;
+ if (!out.d_func()->engine()->clone(d->engine()->handle())) {
+ char block[4096];
+ qint64 totalRead = 0;
+ while (!atEnd()) {
+ qint64 in = read(block, sizeof(block));
+ if (in <= 0)
+ break;
+ totalRead += in;
+ if (in != out.write(block, in)) {
+ close();
+ d->setError(QFile::CopyError, tr("Failure to write block"));
+ error = true;
+ break;
+ }
}
- }
- if (totalRead != size()) {
- // Unable to read from the source. The error string is
- // already set from read().
- error = true;
+ if (totalRead != size()) {
+ // Unable to read from the source. The error string is
+ // already set from read().
+ error = true;
+ }
}
if (!error && !out.rename(newName)) {
error = true;
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 3cb412e47c..b8dca93f61 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -42,6 +42,7 @@
#include "qfilesystemengine_p.h"
#include "qfile.h"
+#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qvarlengtharray.h>
#include <stdlib.h> // for realpath()
@@ -66,6 +67,9 @@
#endif
#if defined(Q_OS_DARWIN)
+# if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
+# include <sys/clonefile.h>
+# endif
// We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but
// we need these declarations:
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
@@ -659,8 +663,22 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
+#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
+ const auto current = QOperatingSystemVersion::current();
+ if (current >= QOperatingSystemVersion::MacOSSierra ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) {
+ if (::clonefile(source.nativeFilePath().constData(),
+ target.nativeFilePath().constData(), 0) == 0)
+ return true;
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+#else
Q_UNUSED(source);
Q_UNUSED(target);
+#endif
error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
return false;
}
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index b1e218de9c..d95a6de777 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -48,7 +48,6 @@
#include "qfile.h"
#include "qdir.h"
-#include "private/qmutexpool_p.h"
#include "qvarlengtharray.h"
#include "qdatetime.h"
#include "qt_windows.h"
@@ -179,6 +178,7 @@ static TRUSTEE_W worldTrusteeW;
static PSID currentUserSID = 0;
static PSID worldSID = 0;
+namespace {
/*
Deletes the allocated SIDs during global static cleanup
*/
@@ -202,25 +202,10 @@ SidCleanup::~SidCleanup()
Q_GLOBAL_STATIC(SidCleanup, initSidCleanup)
-static void resolveLibs()
+struct LibResolver
{
- static bool triedResolve = false;
- if (!triedResolve) {
- // need to resolve the security info functions
-
- // protect initialization
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
- // check triedResolve again, since another thread may have already
- // done the initialization
- if (triedResolve) {
- // another thread did initialize the security function pointers,
- // so we shouldn't do it again.
- return;
- }
-#endif
-
- triedResolve = true;
+ LibResolver()
+ {
HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32");
if (advapiHnd) {
ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW");
@@ -267,9 +252,13 @@ static void resolveLibs()
if (userenvHnd)
ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW");
}
-}
+};
+Q_GLOBAL_STATIC(LibResolver, resolveLibs)
+
+} // anonymous namespace
#endif // QT_CONFIG(fslibs)
+QT_BEGIN_INCLUDE_NAMESPACE
typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD);
static PtrNetShareEnum ptrNetShareEnum = 0;
typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID);
@@ -279,19 +268,13 @@ typedef struct _SHARE_INFO_1 {
DWORD shi1_type;
LPWSTR shi1_remark;
} SHARE_INFO_1;
+QT_END_INCLUDE_NAMESPACE
-
-static bool resolveUNCLibs()
+namespace {
+struct UNCLibResolver
{
- static bool triedResolve = false;
- if (!triedResolve) {
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
- if (triedResolve) {
- return ptrNetShareEnum && ptrNetApiBufferFree;
- }
-#endif
- triedResolve = true;
+ UNCLibResolver()
+ {
#if !defined(Q_OS_WINRT)
HINSTANCE hLib = QSystemLibrary::load(L"Netapi32");
if (hLib) {
@@ -301,6 +284,13 @@ static bool resolveUNCLibs()
}
#endif // !Q_OS_WINRT
}
+};
+Q_GLOBAL_STATIC(UNCLibResolver, uncLibResolver)
+} // anonymous namespace
+
+static bool resolveUNCLibs()
+{
+ uncLibResolver();
return ptrNetShareEnum && ptrNetApiBufferFree;
}
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 0b9cd0557f..de921c0be6 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -860,9 +860,9 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
/*! \fn bool QFSFileEngine::copy(const QString &copyName)
- For windows, copy the file to file \a copyName.
+ For Windows or Apple platforms, copy the file to file \a copyName.
- Not implemented for Unix.
+ Not implemented for other Unix platforms.
*/
/*! \fn QString QFSFileEngine::currentPath(const QString &fileName)
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 593ecc2687..742cebad87 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -108,6 +108,7 @@ public:
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE;
+ bool clone(int sourceHandle) override;
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) Q_DECL_OVERRIDE;
bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE;
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index e152b035e2..4be4e893b3 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -793,6 +793,23 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
#endif
}
+/*!
+ \reimp
+*/
+bool QFSFileEngine::clone(int sourceHandle)
+{
+#if defined(Q_OS_LINUX)
+ Q_D(QFSFileEngine);
+# if !defined FICLONE
+# define FICLONE _IOW (0x94, 9, int)
+# endif
+ return ::ioctl(d->fd, FICLONE, sourceHandle) == 0;
+#else
+ Q_UNUSED(sourceHandle);
+ return false;
+#endif
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FSFILEENGINE
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 7d16e59195..4a477b8429 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -998,4 +998,13 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
return true;
}
+/*!
+ \reimp
+*/
+bool QFSFileEngine::clone(int sourceHandle)
+{
+ Q_UNUSED(sourceHandle);
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 16dab38a60..24fa00c4d9 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1802,6 +1802,8 @@ struct QSettingsIniSection
inline QSettingsIniSection() : position(-1) {}
};
+Q_DECLARE_TYPEINFO(QSettingsIniSection, Q_MOVABLE_TYPE);
+
typedef QMap<QString, QSettingsIniSection> IniMap;
/*
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index 639605d8c4..d8e91e48ce 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -109,6 +109,8 @@ private:
};
#endif
+Q_DECLARE_TYPEINFO(QSettingsKey, Q_MOVABLE_TYPE);
+
typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap;
typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap;
diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h
index 7f365f0e8a..bf40e1627a 100644
--- a/src/corelib/io/qtemporaryfile_p.h
+++ b/src/corelib/io/qtemporaryfile_p.h
@@ -65,7 +65,7 @@ class QTemporaryFilePrivate : public QFilePrivate
{
Q_DECLARE_PUBLIC(QTemporaryFile)
-protected:
+public:
QTemporaryFilePrivate();
explicit QTemporaryFilePrivate(const QString &templateNameIn);
~QTemporaryFilePrivate();
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 226a2401e1..7824559f5f 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -56,6 +56,15 @@ QT_BEGIN_NAMESPACE
typedef QVector<QPair<QModelIndex, QPersistentModelIndex> > QModelIndexPairList;
+struct QSortFilterProxyModelDataChanged
+{
+ QSortFilterProxyModelDataChanged(const QModelIndex &tl, const QModelIndex &br)
+ : topLeft(tl), bottomRight(br) { }
+
+ QModelIndex topLeft;
+ QModelIndex bottomRight;
+};
+
static inline QSet<int> qVectorToSet(const QVector<int> &vector)
{
QSet<int> set;
@@ -164,9 +173,12 @@ public:
bool sort_localeaware;
int filter_column;
- QRegExp filter_regexp;
int filter_role;
+ QRegExp filter_regexp;
+ QModelIndex last_top_source;
+ bool filter_recursive;
+ bool complete_insert;
bool dynamic_sortfilter;
QRowsRemoval itemsBeingRemoved;
@@ -289,6 +301,11 @@ public:
Qt::Orientation orient, int start, int end, int delta_item_count, bool remove);
virtual void _q_sourceModelDestroyed() Q_DECL_OVERRIDE;
+
+ bool needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const;
+
+ bool filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const;
+ bool filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const;
};
typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
@@ -300,6 +317,32 @@ void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
source_index_mapping.clear();
}
+bool QSortFilterProxyModelPrivate::filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
+ return filter_recursive
+ ? filterRecursiveAcceptsRow(source_row, source_parent)
+ : q->filterAcceptsRow(source_row, source_parent);
+}
+
+bool QSortFilterProxyModelPrivate::filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
+
+ if (q->filterAcceptsRow(source_row, source_parent))
+ return true;
+
+ const QModelIndex index = model->index(source_row, 0, source_parent);
+ const int count = model->rowCount(index);
+
+ for (int i = 0; i < count; ++i) {
+ if (filterRecursiveAcceptsRow(i, index))
+ return true;
+ }
+
+ return false;
+}
+
void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent)
{
if (Mapping *m = source_index_mapping.take(source_parent)) {
@@ -340,7 +383,7 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping(
int source_rows = model->rowCount(source_parent);
m->source_rows.reserve(source_rows);
for (int i = 0; i < source_rows; ++i) {
- if (q->filterAcceptsRow(i, source_parent))
+ if (filterAcceptsRowInternal(i, source_parent))
m->source_rows.append(i);
}
int source_cols = model->columnCount(source_parent);
@@ -794,7 +837,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
QVector<int> source_items;
for (int i = start; i <= end; ++i) {
if ((orient == Qt::Vertical)
- ? q->filterAcceptsRow(i, source_parent)
+ ? filterAcceptsRowInternal(i, source_parent)
: q->filterAcceptsColumn(i, source_parent)) {
source_items.append(i);
}
@@ -814,7 +857,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
orthogonal_source_to_proxy.resize(ortho_end);
for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) {
- if ((orient == Qt::Horizontal) ? q->filterAcceptsRow(ortho_item, source_parent)
+ if ((orient == Qt::Horizontal) ? filterAcceptsRowInternal(ortho_item, source_parent)
: q->filterAcceptsColumn(ortho_item, source_parent)) {
orthogonal_proxy_to_source.append(ortho_item);
}
@@ -1125,7 +1168,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
for (int i = 0; i < proxy_to_source.count(); ++i) {
const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical)
- ? !q->filterAcceptsRow(source_item, source_parent)
+ ? !filterAcceptsRowInternal(source_item, source_parent)
: !q->filterAcceptsColumn(source_item, source_parent)) {
// This source item does not satisfy the filter, so it must be removed
source_items_remove.append(source_item);
@@ -1137,7 +1180,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
for (int source_item = 0; source_item < source_count; ++source_item) {
if (source_to_proxy.at(source_item) == -1) {
if ((orient == Qt::Vertical)
- ? q->filterAcceptsRow(source_item, source_parent)
+ ? filterAcceptsRowInternal(source_item, source_parent)
: q->filterAcceptsColumn(source_item, source_parent)) {
// This source item satisfies the filter, so it must be added
source_items_insert.append(source_item);
@@ -1156,6 +1199,33 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
return qVectorToSet(source_items_remove);
}
+bool QSortFilterProxyModelPrivate::needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
+ Q_ASSERT(source_sort_column != -1);
+ const int proxyRowCount = q->rowCount(source_to_proxy(source_parent));
+ // If any modified proxy row no longer passes lessThan(previous, current) or lessThan(current, next) then we need to reorder.
+ return std::any_of(source_rows.begin(), source_rows.end(),
+ [this, q, proxyRowCount, source_parent](int sourceRow) -> bool {
+ const QModelIndex sourceIndex = model->index(sourceRow, source_sort_column, source_parent);
+ const QModelIndex proxyIndex = source_to_proxy(sourceIndex);
+ Q_ASSERT(proxyIndex.isValid()); // caller ensured source_rows were not filtered out
+ if (proxyIndex.row() > 0) {
+ const QModelIndex prevProxyIndex = q->sibling(proxyIndex.row() - 1, proxy_sort_column, proxyIndex);
+ const QModelIndex prevSourceIndex = proxy_to_source(prevProxyIndex);
+ if (sort_order == Qt::AscendingOrder ? q->lessThan(sourceIndex, prevSourceIndex) : q->lessThan(prevSourceIndex, sourceIndex))
+ return true;
+ }
+ if (proxyIndex.row() < proxyRowCount - 1) {
+ const QModelIndex nextProxyIndex = q->sibling(proxyIndex.row() + 1, proxy_sort_column, proxyIndex);
+ const QModelIndex nextSourceIndex = proxy_to_source(nextProxyIndex);
+ if (sort_order == Qt::AscendingOrder ? q->lessThan(nextSourceIndex, sourceIndex) : q->lessThan(sourceIndex, nextSourceIndex))
+ return true;
+ }
+ return false;
+ });
+}
+
void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left,
const QModelIndex &source_bottom_right,
const QVector<int> &roles)
@@ -1163,106 +1233,127 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
Q_Q(QSortFilterProxyModel);
if (!source_top_left.isValid() || !source_bottom_right.isValid())
return;
- QModelIndex source_parent = source_top_left.parent();
- IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
- if (it == source_index_mapping.constEnd()) {
- // Don't care, since we don't have mapping for this index
- return;
+
+ std::vector<QSortFilterProxyModelDataChanged> data_changed_list;
+ data_changed_list.emplace_back(source_top_left, source_bottom_right);
+
+ // Do check parents if the filter role have changed and we are recursive
+ if (filter_recursive && (roles.isEmpty() || roles.contains(filter_role))) {
+ QModelIndex source_parent = source_top_left.parent();
+
+ while (source_parent.isValid()) {
+ data_changed_list.emplace_back(source_parent, source_parent);
+ source_parent = source_parent.parent();
+ }
}
- Mapping *m = it.value();
- // Figure out how the source changes affect us
- QVector<int> source_rows_remove;
- QVector<int> source_rows_insert;
- QVector<int> source_rows_change;
- QVector<int> source_rows_resort;
- int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1);
- for (int source_row = source_top_left.row(); source_row <= end; ++source_row) {
- if (dynamic_sortfilter) {
- if (m->proxy_rows.at(source_row) != -1) {
- if (!q->filterAcceptsRow(source_row, source_parent)) {
- // This source row no longer satisfies the filter, so it must be removed
- source_rows_remove.append(source_row);
- } else if (source_sort_column >= source_top_left.column() && source_sort_column <= source_bottom_right.column()) {
- // This source row has changed in a way that may affect sorted order
- source_rows_resort.append(source_row);
+ for (const QSortFilterProxyModelDataChanged &data_changed : data_changed_list) {
+ const QModelIndex &source_top_left = data_changed.topLeft;
+ const QModelIndex &source_bottom_right = data_changed.bottomRight;
+ const QModelIndex source_parent = source_top_left.parent();
+
+ IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
+ if (it == source_index_mapping.constEnd()) {
+ // Don't care, since we don't have mapping for this index
+ continue;
+ }
+ Mapping *m = it.value();
+
+ // Figure out how the source changes affect us
+ QVector<int> source_rows_remove;
+ QVector<int> source_rows_insert;
+ QVector<int> source_rows_change;
+ QVector<int> source_rows_resort;
+ int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1);
+ for (int source_row = source_top_left.row(); source_row <= end; ++source_row) {
+ if (dynamic_sortfilter) {
+ if (m->proxy_rows.at(source_row) != -1) {
+ if (!filterAcceptsRowInternal(source_row, source_parent)) {
+ // This source row no longer satisfies the filter, so it must be removed
+ source_rows_remove.append(source_row);
+ } else if (source_sort_column >= source_top_left.column() && source_sort_column <= source_bottom_right.column()) {
+ // This source row has changed in a way that may affect sorted order
+ source_rows_resort.append(source_row);
+ } else {
+ // This row has simply changed, without affecting filtering nor sorting
+ source_rows_change.append(source_row);
+ }
} else {
- // This row has simply changed, without affecting filtering nor sorting
- source_rows_change.append(source_row);
+ if (!itemsBeingRemoved.contains(source_parent, source_row) && filterAcceptsRowInternal(source_row, source_parent)) {
+ // This source row now satisfies the filter, so it must be added
+ source_rows_insert.append(source_row);
+ }
}
} else {
- if (!itemsBeingRemoved.contains(source_parent, source_row) && q->filterAcceptsRow(source_row, source_parent)) {
- // This source row now satisfies the filter, so it must be added
- source_rows_insert.append(source_row);
+ if (m->proxy_rows.at(source_row) != -1)
+ source_rows_change.append(source_row);
+ }
+ }
+
+ if (!source_rows_remove.isEmpty()) {
+ remove_source_items(m->proxy_rows, m->source_rows,
+ source_rows_remove, source_parent, Qt::Vertical);
+ QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove);
+ QVector<QModelIndex>::iterator childIt = m->mapped_children.end();
+ while (childIt != m->mapped_children.begin()) {
+ --childIt;
+ const QModelIndex source_child_index = *childIt;
+ if (source_rows_remove_set.contains(source_child_index.row())) {
+ childIt = m->mapped_children.erase(childIt);
+ remove_from_mapping(source_child_index);
}
}
- } else {
- if (m->proxy_rows.at(source_row) != -1)
- source_rows_change.append(source_row);
}
- }
- if (!source_rows_remove.isEmpty()) {
- remove_source_items(m->proxy_rows, m->source_rows,
- source_rows_remove, source_parent, Qt::Vertical);
- QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove);
- QVector<QModelIndex>::iterator childIt = m->mapped_children.end();
- while (childIt != m->mapped_children.begin()) {
- --childIt;
- const QModelIndex source_child_index = *childIt;
- if (source_rows_remove_set.contains(source_child_index.row())) {
- childIt = m->mapped_children.erase(childIt);
- remove_from_mapping(source_child_index);
+ if (!source_rows_resort.isEmpty()) {
+ if (needsReorder(source_rows_resort, source_parent)) {
+ // Re-sort the rows of this level
+ QList<QPersistentModelIndex> parents;
+ parents << q->mapFromSource(source_parent);
+ emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
+ QModelIndexPairList source_indexes = store_persistent_indexes();
+ remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
+ source_parent, Qt::Vertical, false);
+ sort_source_rows(source_rows_resort, source_parent);
+ insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
+ source_parent, Qt::Vertical, false);
+ update_persistent_indexes(source_indexes);
+ emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
}
+ // Make sure we also emit dataChanged for the rows
+ source_rows_change += source_rows_resort;
}
- }
- if (!source_rows_resort.isEmpty()) {
- // Re-sort the rows of this level
- QList<QPersistentModelIndex> parents;
- parents << q->mapFromSource(source_parent);
- emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
- QModelIndexPairList source_indexes = store_persistent_indexes();
- remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
- sort_source_rows(source_rows_resort, source_parent);
- insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
- update_persistent_indexes(source_indexes);
- emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
- // Make sure we also emit dataChanged for the rows
- source_rows_change += source_rows_resort;
- }
-
- if (!source_rows_change.isEmpty()) {
- // Find the proxy row range
- int proxy_start_row;
- int proxy_end_row;
- proxy_item_range(m->proxy_rows, source_rows_change,
- proxy_start_row, proxy_end_row);
- // ### Find the proxy column range also
- if (proxy_end_row >= 0) {
- // the row was accepted, but some columns might still be filtered out
- int source_left_column = source_top_left.column();
- while (source_left_column < source_bottom_right.column()
- && m->proxy_columns.at(source_left_column) == -1)
- ++source_left_column;
- const QModelIndex proxy_top_left = create_index(
- proxy_start_row, m->proxy_columns.at(source_left_column), it);
- int source_right_column = source_bottom_right.column();
- while (source_right_column > source_top_left.column()
- && m->proxy_columns.at(source_right_column) == -1)
- --source_right_column;
- const QModelIndex proxy_bottom_right = create_index(
- proxy_end_row, m->proxy_columns.at(source_right_column), it);
- emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
+ if (!source_rows_change.isEmpty()) {
+ // Find the proxy row range
+ int proxy_start_row;
+ int proxy_end_row;
+ proxy_item_range(m->proxy_rows, source_rows_change,
+ proxy_start_row, proxy_end_row);
+ // ### Find the proxy column range also
+ if (proxy_end_row >= 0) {
+ // the row was accepted, but some columns might still be filtered out
+ int source_left_column = source_top_left.column();
+ while (source_left_column < source_bottom_right.column()
+ && m->proxy_columns.at(source_left_column) == -1)
+ ++source_left_column;
+ const QModelIndex proxy_top_left = create_index(
+ proxy_start_row, m->proxy_columns.at(source_left_column), it);
+ int source_right_column = source_bottom_right.column();
+ while (source_right_column > source_top_left.column()
+ && m->proxy_columns.at(source_right_column) == -1)
+ --source_right_column;
+ const QModelIndex proxy_bottom_right = create_index(
+ proxy_end_row, m->proxy_columns.at(source_right_column), it);
+ emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
+ }
}
- }
- if (!source_rows_insert.isEmpty()) {
- sort_source_rows(source_rows_insert, source_parent);
- insert_source_items(m->proxy_rows, m->source_rows,
- source_rows_insert, source_parent, Qt::Vertical);
+ if (!source_rows_insert.isEmpty()) {
+ sort_source_rows(source_rows_insert, source_parent);
+ insert_source_items(m->proxy_rows, m->source_rows,
+ source_rows_insert, source_parent, Qt::Vertical);
+ }
}
}
@@ -1386,18 +1477,60 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted(
{
Q_UNUSED(start);
Q_UNUSED(end);
+
+ const bool toplevel = !source_parent.isValid();
+ const bool recursive_accepted = filter_recursive && !toplevel && filterAcceptsRowInternal(source_parent.row(), source_parent.parent());
//Force the creation of a mapping now, even if its empty.
//We need it because the proxy can be acessed at the moment it emits rowsAboutToBeInserted in insert_source_items
- if (can_create_mapping(source_parent))
- create_mapping(source_parent);
+ if (!filter_recursive || toplevel || recursive_accepted) {
+ if (can_create_mapping(source_parent))
+ create_mapping(source_parent);
+ if (filter_recursive)
+ complete_insert = true;
+ } else {
+ // The row could have been rejected or the parent might be not yet known... let's try to discover it
+ QModelIndex top_source_parent = source_parent;
+ QModelIndex parent = source_parent.parent();
+ QModelIndex grandParent = parent.parent();
+
+ while (parent.isValid() && !filterAcceptsRowInternal(parent.row(), grandParent)) {
+ top_source_parent = parent;
+ parent = grandParent;
+ grandParent = parent.parent();
+ }
+
+ last_top_source = top_source_parent;
+ }
}
void QSortFilterProxyModelPrivate::_q_sourceRowsInserted(
const QModelIndex &source_parent, int start, int end)
{
- source_items_inserted(source_parent, start, end, Qt::Vertical);
- if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column.
- sort(); // now it should succeed so we need to make sure to sort again
+ if (!filter_recursive || complete_insert) {
+ if (filter_recursive)
+ complete_insert = false;
+ source_items_inserted(source_parent, start, end, Qt::Vertical);
+ if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column.
+ sort(); // now it should succeed so we need to make sure to sort again
+ return;
+ }
+
+ if (filter_recursive) {
+ bool accept = false;
+
+ for (int row = start; row <= end; ++row) {
+ if (filterAcceptsRowInternal(row, source_parent)) {
+ accept = true;
+ break;
+ }
+ }
+
+ if (!accept) // the new rows have no descendants that match the filter, filter them out.
+ return;
+
+ // last_top_source should now become visible
+ _q_sourceDataChanged(last_top_source, last_top_source, QVector<int>());
+ }
}
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
@@ -1413,6 +1546,27 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved(
{
itemsBeingRemoved = QRowsRemoval();
source_items_removed(source_parent, start, end, Qt::Vertical);
+
+ if (filter_recursive) {
+ // Find out if removing this visible row means that some ascendant
+ // row can now be hidden.
+ // We go up until we find a row that should still be visible
+ // and then make QSFPM re-evaluate the last one we saw before that, to hide it.
+
+ QModelIndex to_hide;
+ QModelIndex source_ascendant = source_parent;
+
+ while (source_ascendant.isValid()) {
+ if (filterAcceptsRowInternal(source_ascendant.row(), source_ascendant.parent()))
+ break;
+
+ to_hide = source_ascendant;
+ source_ascendant = source_ascendant.parent();
+ }
+
+ if (to_hide.isValid())
+ _q_sourceDataChanged(to_hide, to_hide, QVector<int>());
+ }
}
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeMoved(
@@ -1685,7 +1839,9 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent)
d->sort_localeaware = false;
d->filter_column = 0;
d->filter_role = Qt::DisplayRole;
+ d->filter_recursive = false;
d->dynamic_sortfilter = true;
+ d->complete_insert = false;
connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping()));
}
@@ -2506,6 +2662,32 @@ void QSortFilterProxyModel::setFilterRole(int role)
}
/*!
+ \since 5.9
+ \property QSortFilterProxyModel::recursiveFiltering
+ \brief whether the filter to be applied recursively on children, and for
+ any matching child, its parents will be visible as well.
+
+ The default value is false.
+
+ \sa filterAcceptsRow()
+*/
+bool QSortFilterProxyModel::recursiveFiltering() const
+{
+ Q_D(const QSortFilterProxyModel);
+ return d->filter_recursive;
+}
+
+void QSortFilterProxyModel::setRecursiveFiltering(bool recursive)
+{
+ Q_D(QSortFilterProxyModel);
+ if (d->filter_recursive == recursive)
+ return;
+ d->filter_about_to_be_changed();
+ d->filter_recursive = recursive;
+ d->filter_changed();
+}
+
+/*!
\obsolete
This function is obsolete. Use invalidate() instead.
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index 06ff79ef5f..6f2e9806ed 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -67,6 +67,7 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
Q_PROPERTY(bool isSortLocaleAware READ isSortLocaleAware WRITE setSortLocaleAware)
Q_PROPERTY(int sortRole READ sortRole WRITE setSortRole)
Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole)
+ Q_PROPERTY(bool recursiveFiltering READ recursiveFiltering WRITE setRecursiveFiltering)
public:
explicit QSortFilterProxyModel(QObject *parent = Q_NULLPTR);
@@ -107,6 +108,9 @@ public:
int filterRole() const;
void setFilterRole(int role);
+ bool recursiveFiltering() const;
+ void setRecursiveFiltering(bool recursive);
+
public Q_SLOTS:
void setFilterRegExp(const QString &pattern);
void setFilterWildcard(const QString &pattern);
diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp
index 0f7472aa5a..da232cc142 100644
--- a/src/corelib/itemmodels/qstringlistmodel.cpp
+++ b/src/corelib/itemmodels/qstringlistmodel.cpp
@@ -131,7 +131,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const
*/
QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &idx) const
{
- if (!idx.isValid() || column != 0 || row >= lst.count())
+ if (!idx.isValid() || column != 0 || row >= lst.count() || row < 0)
return QModelIndex();
return createIndex(row, 0);
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
index 68d9bf180f..961148d9ec 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.h
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -124,6 +124,8 @@ protected:
QObject *parent);
};
+Q_DECLARE_TYPEINFO(QAbstractEventDispatcher::TimerInfo, (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) ? Q_PRIMITIVE_TYPE : Q_RELOCATABLE_TYPE));
+
QT_END_NAMESPACE
#endif // QABSTRACTEVENTDISPATCHER_H
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 231afb991c..a91c02f54e 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -42,7 +42,6 @@
#ifdef Q_OS_OSX
#include <AppKit/NSText.h>
-#include <Carbon/Carbon.h>
#endif
#include <qdebug.h>
@@ -140,6 +139,7 @@ struct qtKey2CocoaKeySortLessThan
}
};
+static const int NSEscapeCharacter = 27; // not defined by Cocoa headers
static const int NumEntries = 59;
static const KeyPair entries[NumEntries] = {
{ NSEnterCharacter, Qt::Key_Enter },
@@ -148,7 +148,7 @@ static const KeyPair entries[NumEntries] = {
{ NSNewlineCharacter, Qt::Key_Return },
{ NSCarriageReturnCharacter, Qt::Key_Return },
{ NSBackTabCharacter, Qt::Key_Backtab },
- { kEscapeCharCode, Qt::Key_Escape },
+ { NSEscapeCharacter, Qt::Key_Escape },
// Cocoa sends us delete when pressing backspace!
// (NB when we reverse this list in qtKey2CocoaKey, there
// will be two indices of Qt::Key_Backspace. But is seems to work
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 8f37aec6e2..c8771bfee5 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -103,6 +103,8 @@ struct sockaddr;
QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(pollfd, Q_PRIMITIVE_TYPE);
+
// Internal operator functions for timespecs
inline timespec &normalizedTimespec(timespec &t)
{
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index d728040343..bcf5b10baa 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -55,7 +55,6 @@
#include "QtCore/qlist.h"
#include "private/qabstracteventdispatcher_p.h"
#include "private/qcore_unix_p.h"
-#include "private/qpodlist_p.h"
#include "QtCore/qvarlengtharray.h"
#include "private/qtimerinfo_unix_p.h"
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index 93bc477e7d..306c0845ef 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -406,7 +406,7 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative,
"runPendingCppRunnablesOnAndroidThread",
"()V");
- g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "()V");
+ g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "(I)V");
g_jNativeClass = static_cast<jclass>(env->NewGlobalRef(jQtNative));
env->DeleteLocalRef(jQtNative);
@@ -566,9 +566,9 @@ void QtAndroidPrivate::unregisterKeyEventListener(QtAndroidPrivate::KeyEventList
g_keyEventListeners()->listeners.removeOne(listener);
}
-void QtAndroidPrivate::hideSplashScreen(JNIEnv *env)
+void QtAndroidPrivate::hideSplashScreen(JNIEnv *env, int duration)
{
- env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID);
+ env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID, duration);
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h
index 62f9358513..9fa47d5302 100644
--- a/src/corelib/kernel/qjnihelpers_p.h
+++ b/src/corelib/kernel/qjnihelpers_p.h
@@ -140,7 +140,7 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener);
Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener);
- Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env);
+ Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env, int duration = 0);
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 3674ebc1a1..5e2e746bbc 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -462,7 +462,8 @@ public:
WeakPointerToQObject = 0x40,
TrackingPointerToQObject = 0x80,
WasDeclaredAsMetaType = 0x100,
- IsGadget = 0x200
+ IsGadget = 0x200,
+ PointerToGadget = 0x400
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@@ -1388,6 +1389,19 @@ namespace QtPrivate
enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
};
+ template<typename T, typename Enable = void>
+ struct IsPointerToGadgetHelper { enum { Value = false }; };
+
+ template<typename T>
+ struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
+ {
+ using BaseType = T;
+ template <typename X>
+ static char checkType(void (X::*)());
+ static void *checkType(void (T::*)());
+ enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
+ };
+
template<typename T> char qt_getEnumMetaObject(const T&);
@@ -1423,6 +1437,11 @@ namespace QtPrivate
static inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
+ struct MetaObjectForType<T, typename QEnableIf<IsPointerToGadgetHelper<T>::Value>::Type>
+ {
+ static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
+ };
+ template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
{
static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
@@ -1578,6 +1597,7 @@ namespace QtPrivate
template <typename T, int =
QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
QtPrivate::IsGadgetHelper<T>::Value ? QMetaType::IsGadget :
+ QtPrivate::IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget :
QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
struct QMetaTypeIdQObject
{
@@ -1631,6 +1651,7 @@ namespace QtPrivate {
| (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
| (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::Value ? QMetaType::IsGadget : 0)
+ | (IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget : 0)
};
};
@@ -1798,6 +1819,30 @@ struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
};
template <typename T>
+struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
+{
+ enum {
+ Defined = 1
+ };
+
+ static int qt_metatype_id()
+ {
+ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if (const int id = metatype_id.loadAcquire())
+ return id;
+ const char * const cName = T::staticMetaObject.className();
+ QByteArray typeName;
+ typeName.reserve(int(strlen(cName)) + 1);
+ typeName.append(cName).append('*');
+ const int newId = qRegisterNormalizedMetaType<T*>(
+ typeName,
+ reinterpret_cast<T**>(quintptr(-1)));
+ metatype_id.storeRelease(newId);
+ return newId;
+ }
+};
+
+template <typename T>
struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
{
enum {
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 1b05962c07..24ad9d140c 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -2339,7 +2339,7 @@ static void err_info_about_objects(const char * func,
a thread different from this object's thread. Do not use this
function in this type of scenario.
- \sa senderSignalIndex(), QSignalMapper
+ \sa senderSignalIndex()
*/
QObject *QObject::sender() const
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index a7d7ef0889..2bdaffb465 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -243,6 +243,7 @@ public:
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};
+Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE);
/*! \internal
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index a483717da5..d56965281e 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -58,10 +58,10 @@ public:
};
-
/*!
\class QSignalMapper
\inmodule QtCore
+ \obsolete
\brief The QSignalMapper class bundles signals from identifiable senders.
\ingroup objectmodel
@@ -108,6 +108,12 @@ public:
widget will emit a single \c clicked() signal whose argument is
the text of the button the user clicked.
+ This class was mostly useful before lambda functions could be used as
+ slots. The example above can be rewritten simpler without QSignalMapper
+ by connecting to a lambda function.
+
+ \snippet qsignalmapper/buttonwidget.cpp 3
+
\sa QObject, QButtonGroup, QActionGroup
*/
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
index f960c7cabf..6c4cfa9627 100644
--- a/src/corelib/kernel/qsignalmapper.h
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -42,6 +42,8 @@
#include <QtCore/qobject.h>
+#if QT_DEPRECATED_SINCE(5, 10)
+
QT_BEGIN_NAMESPACE
class QSignalMapperPrivate;
@@ -51,7 +53,7 @@ class Q_CORE_EXPORT QSignalMapper : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QSignalMapper)
public:
- explicit QSignalMapper(QObject *parent = Q_NULLPTR);
+ QT_DEPRECATED explicit QSignalMapper(QObject *parent = nullptr);
~QSignalMapper();
void setMapping(QObject *sender, int id);
@@ -82,4 +84,6 @@ private:
QT_END_NAMESPACE
+#endif
+
#endif // QSIGNALMAPPER_H
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 5c0acce4c3..ed7ebb2ef5 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -655,7 +655,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
}
// Binary search in the icons or generic-icons list
-QString QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime)
+QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime)
{
const int iconsListOffset = cacheFile->getUint32(posListOffset);
const int numIcons = cacheFile->getUint32(iconsListOffset);
@@ -676,7 +676,7 @@ QString QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset
return QLatin1String(cacheFile->getCharStar(iconOffset));
}
}
- return QString();
+ return QLatin1String();
}
void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
@@ -684,7 +684,7 @@ void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
checkCache();
const QByteArray inputMime = data.name.toLatin1();
for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const QString icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
+ const QLatin1String icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
if (!icon.isEmpty()) {
data.iconName = icon;
return;
@@ -697,7 +697,7 @@ void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
checkCache();
const QByteArray inputMime = data.name.toLatin1();
for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const QString icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
+ const QLatin1String icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
if (!icon.isEmpty()) {
data.genericIconName = icon;
return;
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index f410e62267..0be01d2fd0 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -116,7 +116,7 @@ private:
void matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, const QString &fileName);
bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck);
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
- QString iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
+ QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
void loadMimeTypeList();
void checkCache();
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index 20b4461b03..5ecd339908 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -49,7 +49,6 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
-#include <QtCore/QPair>
#include <QtCore/QXmlStreamReader>
#include <QtCore/QXmlStreamWriter>
#include <QtCore/QStack>
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 21f1007d5b..05f9c68a7b 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -122,8 +122,8 @@ void QFactoryLoader::update()
//
// ### FIXME find a proper solution
//
- const bool isLoadingDebugAndReleaseCocoa = plugins.contains(QStringLiteral("libqcocoa_debug.dylib"))
- && plugins.contains(QStringLiteral("libqcocoa.dylib"));
+ const bool isLoadingDebugAndReleaseCocoa = plugins.contains(QLatin1String("libqcocoa_debug.dylib"))
+ && plugins.contains(QLatin1String("libqcocoa.dylib"));
#endif
for (int j = 0; j < plugins.count(); ++j) {
QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
@@ -131,10 +131,10 @@ void QFactoryLoader::update()
#ifdef Q_OS_MAC
if (isLoadingDebugAndReleaseCocoa) {
#ifdef QT_DEBUG
- if (fileName.contains(QStringLiteral("libqcocoa.dylib")))
+ if (fileName.contains(QLatin1String("libqcocoa.dylib")))
continue; // Skip release plugin in debug mode
#else
- if (fileName.contains(QStringLiteral("libqcocoa_debug.dylib")))
+ if (fileName.contains(QLatin1String("libqcocoa_debug.dylib")))
continue; // Skip debug plugin in release mode
#endif
}
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index be9f632557..6c814ef854 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -196,6 +196,8 @@ public:
} // namespace QtPrivate
+Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
+
#endif //Q_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index 8427b0e696..397d6203aa 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -94,7 +94,7 @@ QT_BEGIN_NAMESPACE
seated (taking the available seats to 5, making the party of 10
people wait longer).
- \sa QMutex, QWaitCondition, QThread, {Semaphores Example}
+ \sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread, {Semaphores Example}
*/
class QSemaphorePrivate {
@@ -152,7 +152,10 @@ void QSemaphore::acquire(int n)
\snippet code/src_corelib_thread_qsemaphore.cpp 1
- \sa acquire(), available()
+ QSemaphoreReleaser is a \l{http://en.cppreference.com/w/cpp/language/raii}{RAII}
+ wrapper around this function.
+
+ \sa acquire(), available(), QSemaphoreReleaser
*/
void QSemaphore::release(int n)
{
@@ -234,6 +237,152 @@ bool QSemaphore::tryAcquire(int n, int timeout)
}
+/*!
+ \class QSemaphoreReleaser
+ \brief The QSemaphoreReleaser class provides exception-safe deferral of a QSemaphore::release() call
+ \since 5.10
+ \ingroup thread
+ \inmodule QtCore
+
+ \reentrant
+
+ QSemaphoreReleaser can be used wherever you would otherwise use
+ QSemaphore::release(). Constructing a QSemaphoreReleaser defers the
+ release() call on the semaphore until the QSemaphoreReleaser is
+ destroyed (see
+ \l{http://en.cppreference.com/w/cpp/language/raii}{RAII pattern}).
+
+ You can use this to reliably release a semaphore to avoid dead-lock
+ in the face of exceptions or early returns:
+
+ \code
+ // ... do something that may throw or return early
+ sem.release();
+ \endcode
+
+ If an early return is taken or an exception is thrown before the
+ \c{sem.release()} call is reached, the semaphore is not released,
+ possibly preventing the thread waiting in the corresponding
+ \c{sem.acquire()} call from ever continuing execution.
+
+ When using RAII instead:
+
+ \code
+ const QSemaphoreReleaser releaser(sem);
+ // ... do something that may throw or early return
+ // implicitly calls sem.release() here and at every other return in between
+ \endcode
+
+ this can no longer happen, because the compiler will make sure that
+ the QSemaphoreReleaser destructor is always called, and therefore
+ the semaphore is always released.
+
+ QSemaphoreReleaser is move-enabled and can therefore be returned
+ from functions to transfer responsibility for releasing a semaphore
+ out of a function or a scope:
+
+ \code
+ { // some scope
+ QSemaphoreReleaser releaser; // does nothing
+ // ...
+ if (someCondition) {
+ releaser = QSemaphoreReleaser(sem);
+ // ...
+ }
+ // ...
+ } // conditionally calls sem.release(), depending on someCondition
+ \endcode
+
+ A QSemaphoreReleaser can be canceled by a call to cancel(). A canceled
+ semaphore releaser will no longer call QSemaphore::release() in its
+ destructor.
+
+ \sa QMutexLocker
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser()
+
+ Default constructor. Creates a QSemaphoreReleaser that does nothing.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphore &sem, int n)
+
+ Constructor. Stores the arguments and calls \a{sem}.release(\a{n})
+ in the destructor.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphore *sem, int n)
+
+ Constructor. Stores the arguments and calls \a{sem}->release(\a{n})
+ in the destructor.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphoreReleaser &&other)
+
+ Move constructor. Takes over responsibility to call QSemaphore::release()
+ from \a other, which in turn is canceled.
+
+ \sa cancel()
+*/
+
+/*!
+ \fn QSemaphoreReleaser::operator=(QSemaphoreReleaser &&other)
+
+ Move assignment operator. Takes over responsibility to call QSemaphore::release()
+ from \a other, which in turn is canceled.
+
+ If this semaphore releaser had the responsibility to call some QSemaphore::release()
+ itself, it performs the call before taking over from \a other.
+
+ \sa cancel()
+*/
+
+/*!
+ \fn QSemaphoreReleaser::~QSemaphoreReleaser()
+
+ Unless canceled, calls QSemaphore::release() with the arguments provided
+ to the constructor, or by the last move assignment.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::swap(QSemaphoreReleaser &other)
+
+ Exchanges the responsibilites of \c{*this} and \a other.
+
+ Unlike move assignment, neither of the two objects ever releases its
+ semaphore, if any, as a consequence of swapping.
+
+ Therefore this function is very fast and never fails.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::semaphore() const
+
+ Returns a pointer to the QSemaphore object provided to the constructor,
+ or by the last move assignment, if any. Otherwise, returns \c nullptr.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::cancel()
+
+ Cancels this QSemaphoreReleaser such that the destructor will no longer
+ call \c{semaphore()->release()}. Returns the value of semaphore()
+ before this call. After this call, semaphore() will return \c nullptr.
+
+ To enable again, assign a new QSemaphoreReleaser:
+
+ \code
+ releaser.cancel(); // avoid releasing old semaphore()
+ releaser = QSemaphoreReleaser(sem, 42);
+ // now will call sem.release(42) when 'releaser' is destroyed
+ \endcode
+*/
+
+
QT_END_NAMESPACE
#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index adb9d73e50..a92740c8ce 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -69,6 +69,45 @@ private:
QSemaphorePrivate *d;
};
+class QSemaphoreReleaser
+{
+ QSemaphore *m_sem = nullptr;
+ int m_n;
+public:
+ QSemaphoreReleaser() = default;
+ explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW
+ : m_sem(&sem), m_n(n) {}
+ explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) Q_DECL_NOTHROW
+ : m_sem(sem), m_n(n) {}
+ QSemaphoreReleaser(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ : m_sem(other.m_sem), m_n(other.m_n)
+ { other.m_sem = nullptr; }
+ QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ { QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
+
+ ~QSemaphoreReleaser()
+ {
+ if (m_sem)
+ m_sem->release(m_n);
+ }
+
+ void swap(QSemaphoreReleaser &other) Q_DECL_NOTHROW
+ {
+ qSwap(m_sem, other.m_sem);
+ qSwap(m_n, other.m_n);
+ }
+
+ QSemaphore *semaphore() const Q_DECL_NOTHROW
+ { return m_sem; }
+
+ QSemaphore *cancel() Q_DECL_NOTHROW
+ {
+ QSemaphore *old = m_sem;
+ m_sem = nullptr;
+ return old;
+ }
+};
+
#endif // QT_NO_THREAD
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 1d3293e85e..085adb1859 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -608,6 +608,24 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QChar::QChar(char16_t ch)
+ \since 5.10
+
+ Constructs a QChar corresponding to the UTF-16 character \a ch.
+
+ \note This constructor is not available on MSVC 2013.
+*/
+
+/*!
+ \fn QChar::QChar(wchar_t ch)
+ \since 5.10
+
+ Constructs a QChar corresponding to the wide character \a ch.
+
+ \note This constructor is only available on Windows.
+*/
+
+/*!
\fn QChar::QChar(char ch)
Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 81ef67d116..a1d31f6a68 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -86,6 +86,13 @@ public:
Q_DECL_CONSTEXPR QChar(int rc) Q_DECL_NOTHROW : ucs(ushort(rc & 0xffff)) {}
Q_DECL_CONSTEXPR QChar(SpecialCharacter s) Q_DECL_NOTHROW : ucs(ushort(s)) {} // implicit
Q_DECL_CONSTEXPR QChar(QLatin1Char ch) Q_DECL_NOTHROW : ucs(ch.unicode()) {} // implicit
+#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
+ Q_DECL_CONSTEXPR QChar(char16_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
+#endif
+#if defined(Q_OS_WIN)
+ Q_STATIC_ASSERT(sizeof(wchar_t) == sizeof(ushort));
+ Q_DECL_CONSTEXPR QChar(wchar_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
+#endif
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) Q_DECL_NOTHROW : ucs(uchar(c)) { }
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 59952bd107..da534908d4 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -89,8 +89,9 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qlocale_data_p.h"
QT_END_INCLUDE_NAMESPACE
-QLocale::Language QLocalePrivate::codeToLanguage(const QChar *code, int len) Q_DECL_NOTHROW
+QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) Q_DECL_NOTHROW
{
+ const auto len = code.size();
if (len != 2 && len != 3)
return QLocale::C;
ushort uc1 = code[0].toLower().unicode();
@@ -131,8 +132,9 @@ QLocale::Language QLocalePrivate::codeToLanguage(const QChar *code, int len) Q_D
return QLocale::C;
}
-QLocale::Script QLocalePrivate::codeToScript(const QChar *code, int len) Q_DECL_NOTHROW
+QLocale::Script QLocalePrivate::codeToScript(QStringView code) Q_DECL_NOTHROW
{
+ const auto len = code.size();
if (len != 4)
return QLocale::AnyScript;
@@ -150,10 +152,12 @@ QLocale::Script QLocalePrivate::codeToScript(const QChar *code, int len) Q_DECL_
return QLocale::AnyScript;
}
-QLocale::Country QLocalePrivate::codeToCountry(const QChar *code, int len) Q_DECL_NOTHROW
+QLocale::Country QLocalePrivate::codeToCountry(QStringView code) Q_DECL_NOTHROW
{
+ const auto len = code.size();
if (len != 2 && len != 3)
return QLocale::AnyCountry;
+
ushort uc1 = code[0].toUpper().unicode();
ushort uc2 = code[1].toUpper().unicode();
ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
@@ -167,48 +171,35 @@ QLocale::Country QLocalePrivate::codeToCountry(const QChar *code, int len) Q_DEC
return QLocale::AnyCountry;
}
-QString QLocalePrivate::languageToCode(QLocale::Language language)
+QLatin1String QLocalePrivate::languageToCode(QLocale::Language language)
{
if (language == QLocale::AnyLanguage)
- return QString();
+ return QLatin1String();
if (language == QLocale::C)
return QLatin1String("C");
const unsigned char *c = language_code_list + 3*(uint(language));
- QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
+ return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
- code[0] = ushort(c[0]);
- code[1] = ushort(c[1]);
- if (c[2] != 0)
- code[2] = ushort(c[2]);
-
- return code;
}
-QString QLocalePrivate::scriptToCode(QLocale::Script script)
+QLatin1String QLocalePrivate::scriptToCode(QLocale::Script script)
{
if (script == QLocale::AnyScript || script > QLocale::LastScript)
- return QString();
+ return QLatin1String();
const unsigned char *c = script_code_list + 4*(uint(script));
- return QString::fromLatin1((const char *)c, 4);
+ return QLatin1String(reinterpret_cast<const char *>(c), 4);
}
-QString QLocalePrivate::countryToCode(QLocale::Country country)
+QLatin1String QLocalePrivate::countryToCode(QLocale::Country country)
{
if (country == QLocale::AnyCountry)
- return QString();
+ return QLatin1String();
const unsigned char *c = country_code_list + 3*(uint(country));
- QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
-
- code[0] = ushort(c[0]);
- code[1] = ushort(c[1]);
- if (c[2] != 0)
- code[2] = ushort(c[2]);
-
- return code;
+ return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
}
// http://www.unicode.org/reports/tr35/#Likely_Subtags
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index f7adb021b6..2b3c6a07cc 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -349,23 +349,16 @@ public:
QByteArray bcp47Name(char separator = '-') const;
- // ### QByteArray::fromRawData would be more optimal
- inline QString languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); }
- inline QString scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); }
- inline QString countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); }
-
- static QString languageToCode(QLocale::Language language);
- static QString scriptToCode(QLocale::Script script);
- static QString countryToCode(QLocale::Country country);
- static QLocale::Language codeToLanguage(const QChar *code, int len) Q_DECL_NOTHROW;
- static QLocale::Language codeToLanguage(const QString &code) Q_DECL_NOTHROW { return codeToLanguage(code.data(), code.size()); }
- static QLocale::Language codeToLanguage(const QStringRef &code) Q_DECL_NOTHROW { return codeToLanguage(code.data(), code.size()); }
- static QLocale::Script codeToScript(const QChar *code, int len) Q_DECL_NOTHROW;
- static QLocale::Script codeToScript(const QString &code) Q_DECL_NOTHROW { return codeToScript(code.data(), code.size()); }
- static QLocale::Script codeToScript(const QStringRef &code) Q_DECL_NOTHROW { return codeToScript(code.data(), code.size()); }
- static QLocale::Country codeToCountry(const QChar *code, int len) Q_DECL_NOTHROW;
- static QLocale::Country codeToCountry(const QString &code) Q_DECL_NOTHROW { return codeToCountry(code.data(), code.size()); }
- static QLocale::Country codeToCountry(const QStringRef &code) Q_DECL_NOTHROW { return codeToCountry(code.data(), code.size()); }
+ inline QLatin1String languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); }
+ inline QLatin1String scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); }
+ inline QLatin1String countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); }
+
+ static QLatin1String languageToCode(QLocale::Language language);
+ static QLatin1String scriptToCode(QLocale::Script script);
+ static QLatin1String countryToCode(QLocale::Country country);
+ static QLocale::Language codeToLanguage(QStringView code) Q_DECL_NOTHROW;
+ static QLocale::Script codeToScript(QStringView code) Q_DECL_NOTHROW;
+ static QLocale::Country codeToCountry(QStringView code) Q_DECL_NOTHROW;
static void getLangAndCountry(const QString &name, QLocale::Language &lang,
QLocale::Script &script, QLocale::Country &cntry);
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 325b71f267..558a456515 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -159,6 +159,8 @@ private:
qint64 bufferSize;
};
+Q_DECLARE_TYPEINFO(QRingBuffer, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
#endif // QRINGBUFFER_P_H
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index f6164e2297..59a8dd9d0c 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -261,7 +261,7 @@
# endif
#endif
-#if defined(__AES__) || defined(__PCLMUL__)
+#if defined(__AES__) || defined(__PCLMUL__) || (defined(QT_COMPILER_SUPPORTS_AES) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
# include <wmmintrin.h>
#endif
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 48f3d64c4a..68f5605598 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -165,8 +165,8 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
namespace {
template <uint MaxCount> struct UnrollTailLoop
{
- template <typename RetType, typename Functor1, typename Functor2>
- static inline RetType exec(int count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, int i = 0)
+ template <typename RetType, typename Functor1, typename Functor2, typename Number>
+ static inline RetType exec(Number count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, Number i = 0)
{
/* equivalent to:
* while (count--) {
@@ -188,18 +188,18 @@ template <uint MaxCount> struct UnrollTailLoop
return UnrollTailLoop<MaxCount - 1>::exec(count - 1, returnIfExited, loopCheck, returnIfFailed, i + 1);
}
- template <typename Functor>
- static inline void exec(int count, Functor code)
+ template <typename Functor, typename Number>
+ static inline void exec(Number count, Functor code)
{
/* equivalent to:
- * for (int i = 0; i < count; ++i)
+ * for (Number i = 0; i < count; ++i)
* code(i);
*/
- exec(count, 0, [=](int i) -> bool { code(i); return false; }, [](int) { return 0; });
+ exec(count, 0, [=](Number i) -> bool { code(i); return false; }, [](Number) { return 0; });
}
};
-template <> template <typename RetType, typename Functor1, typename Functor2>
-inline RetType UnrollTailLoop<0>::exec(int, RetType returnIfExited, Functor1, Functor2, int)
+template <> template <typename RetType, typename Functor1, typename Functor2, typename Number>
+inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1, Functor2, Number)
{
return returnIfExited;
}
@@ -379,9 +379,9 @@ static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const u
if (a == b)
return (ae - be);
if (a == 0)
- return 1;
+ return be - b;
if (b == 0)
- return -1;
+ return a - ae;
const ushort *e = ae;
if (be - b < ae - a)
@@ -410,13 +410,10 @@ static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const u
// Case-insensitive comparison between a Unicode string and a QLatin1String
static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b, const uchar *be)
{
- if (a == 0) {
- if (b == 0)
- return 0;
- return 1;
- }
- if (b == 0)
- return -1;
+ if (!a)
+ return be - b;
+ if (!b)
+ return a - ae;
const ushort *e = ae;
if (be - b < ae - a)
@@ -445,7 +442,7 @@ extern "C" int qt_ucstrncmp_mips_dsp_asm(const ushort *a,
#endif
// Unicode case-sensitive compare two same-sized strings
-static int ucstrncmp(const QChar *a, const QChar *b, int l)
+static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
{
#ifdef __OPTIMIZE_SIZE__
const QChar *end = a + l;
@@ -458,6 +455,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
return 0;
#else
#if defined(__mips_dsp)
+ Q_STATIC_ASSERT(sizeof(uint) == sizeof(size_t));
if (l >= 8) {
return qt_ucstrncmp_mips_dsp_asm(reinterpret_cast<const ushort*>(a),
reinterpret_cast<const ushort*>(b),
@@ -484,13 +482,11 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
- reinterpret_cast<const QChar *>(ptr + distance + idx)->unicode();
}
}
-# if defined(Q_COMPILER_LAMBDA)
- const auto &lambda = [=](int i) -> int {
+ const auto lambda = [=](size_t i) -> int {
return reinterpret_cast<const QChar *>(ptr)[i].unicode()
- reinterpret_cast<const QChar *>(ptr + distance)[i].unicode();
};
return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
-# endif
#endif
#if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
if (l >= 8) {
@@ -511,7 +507,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
}
l &= 7;
}
- const auto &lambda = [=](int i) -> int {
+ const auto lambda = [=](size_t i) -> int {
return a[i].unicode() - b[i].unicode();
};
return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
@@ -640,8 +636,8 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
uc += offset;
c += offset;
-# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
- const auto &lambda = [=](int i) { return uc[i] - ushort(c[i]); };
+# if !defined(__OPTIMIZE_SIZE__)
+ const auto lambda = [=](size_t i) { return uc[i] - ushort(c[i]); };
return UnrollTailLoop<MaxTailLength>::exec(e - uc, 0, lambda, lambda);
# endif
#endif
@@ -672,7 +668,7 @@ static int ucstrnicmp(const ushort *a, const ushort *b, int l)
return ucstricmp(a, a + l, b, b + l);
}
-static bool qMemEquals(const quint16 *a, const quint16 *b, int length)
+static bool qMemEquals(const quint16 *a, const quint16 *b, size_t length)
{
if (a == b || !length)
return true;
@@ -8316,6 +8312,76 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa QString, QLatin1Char, {QStringLiteral()}{QStringLiteral}
*/
+/*!
+ \typedef QLatin1String::value_type
+ \since 5.10
+
+ Alias for \c{const char}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::difference_type
+ \since 5.10
+
+ Alias for \c{int}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::size_type
+ \since 5.10
+
+ Alias for \c{int}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::reference
+ \since 5.10
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::iterator
+ \since 5.10
+
+ This typedef provides an STL-style const iterator for QLatin1String.
+
+ QLatin1String does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QLatin1String::const_iterator
+ \since 5.10
+
+ This typedef provides an STL-style const iterator for QLatin1String.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QLatin1String::reverse_iterator
+ \since 5.10
+
+ This typedef provides an STL-style const reverse iterator for QLatin1String.
+
+ QLatin1String does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QLatin1String::const_reverse_iterator
+ \since 5.10
+
+ This typedef provides an STL-style const reverse iterator for QLatin1String.
+
+ \sa reverse_iterator, const_iterator
+*/
+
/*! \fn QLatin1String::QLatin1String()
\since 5.6
@@ -8370,6 +8436,24 @@ QString &QString::setRawData(const QChar *unicode, int size)
Returns the size of the Latin-1 string stored in this object.
*/
+/*! \fn bool QLatin1String::isNull() const
+ \since 5.10
+
+ Returns whether the Latin-1 string stored in this object is null
+ (\c{data() == nullptr}) or not.
+
+ \sa isEmpty(), data()
+*/
+
+/*! \fn bool QLatin1String::isEmpty() const
+ \since 5.10
+
+ Returns whether the Latin-1 string stored in this object is empty
+ (\c{size() == 0}) or not.
+
+ \sa isNull(), size()
+*/
+
/*! \fn QLatin1Char QLatin1String::at(int pos) const
\since 5.8
@@ -8392,6 +8476,97 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa at()
*/
+/*!
+ \fn QLatin1String::const_iterator QLatin1String::begin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
+ the string.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QLatin1String::const_iterator QLatin1String::cbegin() const
+ \since 5.10
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QLatin1String::const_iterator QLatin1String::end() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ character after the last character in the list.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QLatin1String::const_iterator QLatin1String::cend() const
+ \since 5.10
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::rbegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::crbegin() const
+ \since 5.10
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::rend() const
+ \since 5.10
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::crend() const
+ \since 5.10
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
/*! \fn QLatin1String QLatin1String::mid(int start) const
\since 5.8
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 1bd436c387..2b7118e960 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -73,6 +73,10 @@ Q_FORWARD_DECLARE_CF_TYPE(CFString);
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
#endif
+#ifndef QT_STRINGVIEW_LEVEL
+# define QT_STRINGVIEW_LEVEL 1
+#endif
+
QT_BEGIN_NAMESPACE
class QCharRef;
@@ -83,6 +87,7 @@ class QString;
class QStringList;
class QTextCodec;
class QStringRef;
+class QStringView;
template <typename T> class QVector;
class QLatin1String
@@ -97,17 +102,42 @@ public:
Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; }
Q_DECL_CONSTEXPR const char *data() const Q_DECL_NOTHROW { return m_data; }
- Q_DECL_CONSTEXPR QLatin1Char at(int i) const { return QLatin1Char(m_data[i]); }
+ Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !data(); }
+ Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return !size(); }
+
+ Q_DECL_CONSTEXPR QLatin1Char at(int i) const
+ { return Q_ASSERT(i >= 0), Q_ASSERT(i < size()), QLatin1Char(m_data[i]); }
Q_DECL_CONSTEXPR QLatin1Char operator[](int i) const { return at(i); }
+ using value_type = const char;
+ using reference = value_type&;
+ using const_reference = reference;
+ using iterator = value_type*;
+ using const_iterator = iterator;
+ using difference_type = int; // violates Container concept requirements
+ using size_type = int; // violates Container concept requirements
+
+ Q_DECL_CONSTEXPR const_iterator begin() const Q_DECL_NOTHROW { return data(); }
+ Q_DECL_CONSTEXPR const_iterator cbegin() const Q_DECL_NOTHROW { return data(); }
+ Q_DECL_CONSTEXPR const_iterator end() const Q_DECL_NOTHROW { return data() + size(); }
+ Q_DECL_CONSTEXPR const_iterator cend() const Q_DECL_NOTHROW { return data() + size(); }
+
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = reverse_iterator;
+
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+
Q_DECL_CONSTEXPR QLatin1String mid(int pos) const
- { return QLatin1String(m_data + pos, m_size - pos); }
+ { return Q_ASSERT(pos >= 0), Q_ASSERT(pos <= size()), QLatin1String(m_data + pos, m_size - pos); }
Q_DECL_CONSTEXPR QLatin1String mid(int pos, int n) const
- { return QLatin1String(m_data + pos, n); }
+ { return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QLatin1String(m_data + pos, n); }
Q_DECL_CONSTEXPR QLatin1String left(int n) const
- { return QLatin1String(m_data, n); }
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, n); }
Q_DECL_CONSTEXPR QLatin1String right(int n) const
- { return QLatin1String(m_data + m_size - n, n); }
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data + m_size - n, n); }
inline bool operator==(const QString &s) const Q_DECL_NOTHROW;
inline bool operator!=(const QString &s) const Q_DECL_NOTHROW;
@@ -652,7 +682,7 @@ public:
{}
template <int N>
inline QString &operator=(const char (&ch)[N])
- { return (*this = fromLatin1(ch, N - 1)); }
+ { return (*this = fromUtf8(ch, N - 1)); }
#endif
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
inline QT_ASCII_CAST_WARN QString(const char *ch)
@@ -850,6 +880,7 @@ private:
friend class QCharRef;
friend class QTextCodec;
friend class QStringRef;
+ friend class QStringView;
friend class QByteArray;
friend class QCollator;
friend struct QAbstractConcatenable;
@@ -1549,6 +1580,10 @@ inline QStringRef::QStringRef(const QString *aString, int aPosition, int aSize)
inline QStringRef::QStringRef(const QString *aString)
:m_string(aString), m_position(0), m_size(aString?aString->size() : 0){}
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtCore/qstringview.h>
+QT_END_INCLUDE_NAMESPACE
+
// QStringRef <> QStringRef
Q_CORE_EXPORT bool operator==(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW;
inline bool operator!=(const QStringRef &s1, const QStringRef &s2) Q_DECL_NOTHROW
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 75ff934f15..d65563f76d 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -299,6 +299,16 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString
return res;
}
+template<typename T>
+static bool stringList_contains(const QStringList &stringList, const T &str, Qt::CaseSensitivity cs)
+{
+ for (const auto &string : stringList) {
+ if (string.size() == str.size() && string.compare(str, cs) == 0)
+ return true;
+ }
+ return false;
+}
+
/*!
\fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
@@ -312,12 +322,24 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString
bool QtPrivate::QStringList_contains(const QStringList *that, const QString &str,
Qt::CaseSensitivity cs)
{
- for (int i = 0; i < that->size(); ++i) {
- const QString & string = that->at(i);
- if (string.length() == str.length() && str.compare(string, cs) == 0)
- return true;
- }
- return false;
+ return stringList_contains(*that, str, cs);
+}
+
+/*!
+ \fn bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
+ \overload
+ \since 5.10
+
+ Returns \c true if the list contains the string \a str; otherwise
+ returns \c false. The search is case insensitive if \a cs is
+ Qt::CaseInsensitive; the search is case sensitive by default.
+
+ \sa indexOf(), lastIndexOf(), QString::contains()
+ */
+bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str,
+ Qt::CaseSensitivity cs)
+{
+ return stringList_contains(*that, str, cs);
}
#ifndef QT_NO_REGEXP
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index 720d7d7419..b11856d9be 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -120,6 +120,7 @@ public:
#endif
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
inline QStringList operator+(const QStringList &other) const
{ QStringList n = *this; n += other; return n; }
@@ -165,6 +166,7 @@ namespace QtPrivate {
Qt::CaseSensitivity cs);
bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, const QString &str, Qt::CaseSensitivity cs);
+ bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, QLatin1String str, Qt::CaseSensitivity cs);
void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QString &before, const QString &after,
Qt::CaseSensitivity cs);
@@ -222,6 +224,11 @@ inline bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) co
return QtPrivate::QStringList_contains(this, str, cs);
}
+inline bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
+{
+ return QtPrivate::QStringList_contains(this, str, cs);
+}
+
inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp
new file mode 100644
index 0000000000..8504b941b3
--- /dev/null
+++ b/src/corelib/tools/qstringview.cpp
@@ -0,0 +1,533 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 "qstringview.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStringView
+ \inmodule QtCore
+ \since 5.10
+ \brief The QStringView class provides a unified view on UTF-16 strings
+ \reentrant
+ \ingroup tools
+ \ingroup string-processing
+
+ QStringView provides a read-only subset of the QString API.
+
+ A string view explicitly stores a portion of a UTF-16 string it does
+ not own. It acts as an interface type to all kinds of UTF-16 string,
+ without the need to construct a QString first.
+
+ The UTF-16 string may be represented as an array (or an array-compatible
+ data-structure such as QString,
+ std::basic_string, etc.) of \c QChar, \c ushort, \c char16_t (on compilers that
+ support C++11 Unicode strings) or (on platforms, such as Windows,
+ where it is a 16-bit type) \c wchar_t.
+
+ QStringView is designed as an interface type; its main use-case is
+ as a function parameter type. When QStringViews are used as automatic
+ variables or data members, care must be taken to ensure that the referenced
+ string data (for example, owned by a QString) outlives the QStringView on all code paths,
+ lest the string view ends up referencing deleted data.
+
+ When used as an interface type, QStringView allows a single function to accept
+ a wide variety of UTF-16 string data sources. One function accepting QStringView
+ thus replaces three function overloads (taking QString, QStringRef, and
+ \c{(const QChar*, int)}), while at the same time enabling even more string data
+ sources to be passed to the function, such as \c{u"Hello World"}, a \c char16_t
+ string literal.
+
+ QStringViews should be passed by value, not by reference-to-const:
+ \code
+ void myfun1(QStringView sv); // preferred
+ void myfun2(const QStringView &sv); // compiles and works, but slower
+ \endcode
+
+ If you want to give your users maximum freedom in what strings they can pass
+ to your function, accompany the QStringView overload with overloads for
+
+ \list
+ \li \e QChar: this overload can delegate to the QStringView version:
+ \code
+ void fun(QChar ch) { fun(QStringView(&ch, 1)); }
+ \endcode
+ even though, for technical reasons, QStringView cannot provide a
+ QChar constructor by itself.
+ \li \e QString: if you store an unmodified copy of the string and thus would
+ like to take advantage of QString's implicit sharing.
+ \li QLatin1String: if you can implement the function without converting the
+ QLatin1String to UTF-16 first; users expect a function overloaded on
+ QLatin1String to perform strictly less memory allocations than the
+ semantically equivalent call of the QStringView version, involving
+ construction of a QString from the QLatin1String.
+ \endlist
+
+ QStringView can also be used as the return value of a function. If you call a
+ function returning QStringView, take extra care to not keep the QStringView
+ around longer than the function promises to keep the referenced string data alive.
+ If in doubt, obtain a strong reference to the data by calling toString() to convert
+ the QStringView into a QString.
+
+ QStringView is a \e{Literal Type}.
+
+ \note We strongly discourage the use of QList<QStringView>,
+ because QList is a very inefficient container for QStringViews (it would heap-allocate
+ every element). Use QVector (or std::vector) to hold QStringViews instead.
+
+ \sa QString, QStringRef
+*/
+
+/*!
+ \typedef QStringView::value_type
+
+ Alias for \c{const QChar}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::difference_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::size_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+
+ Unlike other Qt classes, QStringView uses \c ptrdiff_t as its \c size_type, to allow
+ accepting data from \c{std::basic_string} without truncation. The Qt API functions,
+ for example length(), return \c int, while the STL-compatible functions, for example
+ size(), return \c size_type.
+*/
+
+/*!
+ \typedef QStringView::reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+
+ QStringView does not support mutable references, so this is the same
+ as const_reference.
+*/
+
+/*!
+ \typedef QStringView::const_reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+
+ QStringView does not support mutable pointers, so this is the same
+ as const_pointer.
+*/
+
+/*!
+ \typedef QStringView::const_pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::iterator
+
+ This typedef provides an STL-style const iterator for QStringView.
+
+ QStringView does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QStringView::const_iterator
+
+ This typedef provides an STL-style const iterator for QStringView.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QStringView::reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QStringView.
+
+ QStringView does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QStringView::const_reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QStringView.
+
+ \sa reverse_iterator, const_iterator
+*/
+
+/*!
+ \fn QStringView::QStringView()
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QStringView::QStringView(std::nullptr_t)
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QStringView::QStringView(QString::Null)
+ \internal
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QStringView::QStringView(const Char *str, size_type len)
+
+ Constructs a string view on \a str with length \a len.
+
+ The range \c{[str,len)} must remain valid for the lifetime of this string view object.
+
+ Passing \c nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
+
+ The behavior is undefined if \a len is negative or, when positive, if \a str is \c nullptr.
+
+ This constructor only participates in overload resolution if \c Char is a compatible
+ character type. The compatible character types are: \c QChar, \c ushort, \c char16_t and
+ (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t.
+*/
+
+/*!
+ \fn QStringView::QStringView(const Char *str)
+
+ Constructs a string view on \a str. The length is determined
+ by scanning for the first \c{char16_t(0)}.
+
+ \a str must remain valid for the lifetime of this string view object.
+
+ Passing \c nullptr as \a str is safe and results in a null string view.
+
+ This constructor only participates in overload resolution if \c Char is a compatible
+ character type. The compatible character types are: \c QChar, \c ushort, \c char16_t and
+ (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t.
+*/
+
+/*!
+ \fn QStringView::QStringView(const QString &str)
+
+ Constructs a string view on \a str.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ The string view will be null if and only if \c{str.isNull()}.
+*/
+
+/*!
+ \fn QStringView::QStringView(const QStringRef &str)
+
+ Constructs a string view on \a str.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ The string view will be null if and only if \c{str.isNull()}.
+*/
+
+/*!
+ \fn QStringView::QStringView(const StdBasicString &str)
+
+ Constructs a string view on \a str. The length is taken from \c{str.size()}.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ This constructor only participates in overload resolution if \c StdBasicString is an
+ instantiation of \c std::basic_string with a compatible character type. The
+ compatible character types are: \c QChar, \c ushort, \c char16_t and
+ (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t.
+
+ The string view will be empty if and only if \c{str.empty()}. It is unspecified
+ whether this constructor can result in a null string view (\c{str.data()} would
+ have to return \c nullptr for this).
+
+ \sa isNull(), isEmpty()
+*/
+
+/*!
+ \fn QString QStringView::toString() const
+
+ Returns a deep copy of this string view's data as a QString.
+
+ The return value will be the null QString if and only if this string view is null.
+
+ \warning QStringView can store strings with more than 2\sup{30} characters
+ while QString cannot. Calling this function on a string view for which size()
+ returns a value greater than \c{INT_MAX / 2} constitutes undefined behavior.
+*/
+
+/*!
+ \fn const QChar *QStringView::data() const
+
+ Returns a const pointer to the first character in the string.
+
+ \sa begin(), end()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::begin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
+ the string.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::cbegin() const
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::end() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ character after the last character in the list.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QStringView::const_iterator QStringView::cend() const
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::rbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::crbegin() const
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::rend() const
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::crend() const
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
+/*!
+ \fn bool QStringView::empty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size(), length()
+*/
+
+/*!
+ \fn bool QStringView::isEmpty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa empty(), isNull(), size(), length()
+*/
+
+/*!
+ \fn bool QStringView::isNull() const
+
+ Returns whether this string view is null - that is, whether \c{data() == nullptr}.
+
+ This functions is provided for compatibility with other Qt containers.
+
+ \sa empty(), isEmpty(), size(), length()
+*/
+
+/*!
+ \fn QStringView::size_type QStringView::size() const
+
+ Returns the size of this string view, in UTF-16 code points (that is,
+ surrogate pairs count as two for the purposes of this function, the same
+ as in QString and QStringRef).
+
+ \sa empty(), isEmpty(), isNull(), length()
+*/
+
+/*!
+ \fn int QStringView::length() const
+
+ Same as size(), except returns the result as an \c int.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning QStringView can represent strings with more than 2\sup{31} characters.
+ Calling this function on a string view for which size() returns a value greater
+ than \c{INT_MAX} constitutes undefined behavior.
+
+ \sa empty(), isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn QChar QStringView::operator[](size_type n) const
+
+ Returns the character at position \a n in this string view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa at(), front(), back()
+*/
+
+/*!
+ \fn QChar QStringView::at(size_type n) const
+
+ Returns the character at position \a n in this string view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa operator[](), front(), back()
+*/
+
+/*!
+ \fn QChar QStringView::front() const
+
+ Returns the first character in the string. Same as first().
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa back(), first(), last()
+*/
+
+/*!
+ \fn QChar QStringView::back() const
+
+ Returns the last character in the string. Same as last().
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa front(), first(), last()
+*/
+
+/*!
+ \fn QChar QStringView::first() const
+
+ Returns the first character in the string. Same as front().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa front(), back(), last()
+*/
+
+/*!
+ \fn QChar QStringView::last() const
+
+ Returns the last character in the string. Same as back().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa back(), front(), first()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
new file mode 100644
index 0000000000..5384e73039
--- /dev/null
+++ b/src/corelib/tools/qstringview.h
@@ -0,0 +1,226 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** 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 QSTRING_H
+# include <QtCore/qstring.h>
+#endif
+
+#ifndef QSTRINGVIEW_H
+#define QSTRINGVIEW_H
+
+#include <string>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_UNICODE_LITERAL
+# ifndef QT_UNICODE_LITERAL
+# error "If you change QStringLiteral, please change QStringViewLiteral, too"
+# endif
+# define QStringViewLiteral(str) QStringView(QT_UNICODE_LITERAL(str), sizeof(str) - 1)
+#endif
+
+namespace QtPrivate {
+template <typename Char>
+struct IsCompatibleCharTypeHelper
+ : std::integral_constant<bool,
+ std::is_same<Char, QChar>::value ||
+ std::is_same<Char, ushort>::value ||
+#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
+ std::is_same<Char, char16_t>::value ||
+#endif
+ (std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {};
+template <typename Char>
+struct IsCompatibleCharType
+ : IsCompatibleCharTypeHelper<typename std::remove_cv<typename std::remove_reference<Char>::type>::type> {};
+
+template <typename T>
+struct IsCompatibleStdBasicStringHelper : std::false_type {};
+template <typename Char, typename...Args>
+struct IsCompatibleStdBasicStringHelper<std::basic_string<Char, Args...> >
+ : IsCompatibleCharType<Char> {};
+
+template <typename T>
+struct IsCompatibleStdBasicString
+ : IsCompatibleStdBasicStringHelper<
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type
+ > {};
+
+} // namespace QtPrivate
+
+class QStringView
+{
+#if defined(Q_OS_WIN) && !defined(Q_COMPILER_UNICODE_STRINGS)
+ typedef wchar_t storage_type;
+#else
+ typedef char16_t storage_type;
+#endif
+public:
+ typedef const QChar value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef QIntegerForSizeof<size_t>::Signed size_type;
+ typedef value_type &reference;
+ typedef value_type &const_reference;
+ typedef value_type *pointer;
+ typedef value_type *const_pointer;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+private:
+ template <typename Char>
+ using if_compatible_char = typename std::enable_if<QtPrivate::IsCompatibleCharType<Char>::value, bool>::type;
+
+ template <typename T>
+ using if_compatible_string = typename std::enable_if<QtPrivate::IsCompatibleStdBasicString<T>::value, bool>::type;
+
+ template <typename Char>
+ static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelper(const Char *str) Q_DECL_NOTHROW
+ {
+ size_type result = 0;
+ while (*str++)
+ ++result;
+ return result;
+ }
+ static Q_DECL_RELAXED_CONSTEXPR size_type lengthHelper(const QChar *str) Q_DECL_NOTHROW
+ {
+ size_type result = 0;
+ while (!str++->isNull())
+ ++result;
+ return result;
+ }
+
+ template <typename Char>
+ static const storage_type *castHelper(const Char *str) Q_DECL_NOTHROW
+ { return reinterpret_cast<const storage_type*>(str); }
+ static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *str) Q_DECL_NOTHROW
+ { return str; }
+
+ // prevent
+ // T t; QStringView sv(t), T \in {QChar, QLatin1String, QByteArray, const char*}
+ // from compiling as QStringView sv(QString(t)):
+ QStringView(QChar) = delete;
+ QStringView(QLatin1String) = delete;
+ QStringView(const QByteArray &) = delete;
+ QStringView(const char *) = delete;
+
+#ifdef Q_OS_WIN
+ // prevent QStringView(Char), Char compatible, from compiling due to:
+ // https://connect.microsoft.com/VisualStudio/feedback/details/2256407/c-two-user-defined-conversions-incorrectly-accepted-in-implicit-conversion-sequence
+ template <typename Char, if_compatible_char<Char> = true>
+ QStringView(Char) = delete;
+#endif
+public:
+ Q_DECL_CONSTEXPR QStringView() Q_DECL_NOTHROW
+ : m_size(0), m_data(nullptr) {}
+ Q_DECL_CONSTEXPR QStringView(std::nullptr_t) Q_DECL_NOTHROW
+ : QStringView() {}
+#if QT_DEPRECATED_SINCE(5, 9)
+ Q_DECL_CONSTEXPR QStringView(QString::Null) Q_DECL_NOTHROW
+ : QStringView() {}
+#endif
+
+ template <typename Char, if_compatible_char<Char> = true>
+ Q_DECL_CONSTEXPR QStringView(const Char *str, size_type len)
+ : m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)),
+ m_data(castHelper(str)) {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ Q_DECL_CONSTEXPR QStringView(const Char *str)
+ : QStringView(str, str ? lengthHelper(str) : 0) {}
+
+ QStringView(const QString &str) Q_DECL_NOTHROW
+ : QStringView(str.isNull() ? nullptr : str.data(), size_type(str.size())) {}
+ QStringView(const QStringRef &str) Q_DECL_NOTHROW
+ : QStringView(str.isNull() ? nullptr : str.data(), size_type(str.size())) {}
+
+ template <typename StdBasicString, if_compatible_string<StdBasicString> = true>
+ QStringView(const StdBasicString &str) Q_DECL_NOTHROW
+ : QStringView(str.data(), size_type(str.size())) {}
+
+ QString toString() const { return Q_ASSERT(size() == length()), QString(data(), length()); }
+
+ Q_DECL_CONSTEXPR size_type size() const Q_DECL_NOTHROW { return m_size; }
+ const_pointer data() const Q_DECL_NOTHROW { return reinterpret_cast<const_pointer>(m_data); }
+ Q_DECL_CONSTEXPR const storage_type *utf16() const Q_DECL_NOTHROW { return m_data; }
+
+ Q_DECL_CONSTEXPR QChar operator[](size_type n) const
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n < size()), QChar(m_data[n]); }
+
+ //
+ // QString API
+ //
+
+ Q_DECL_CONSTEXPR QChar at(size_type n) const { return (*this)[n]; }
+
+ //
+ // STL compatibility API:
+ //
+ const_iterator begin() const Q_DECL_NOTHROW { return data(); }
+ const_iterator end() const Q_DECL_NOTHROW { return data() + size(); }
+ const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
+ const_iterator cend() const Q_DECL_NOTHROW { return end(); }
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+
+ Q_DECL_CONSTEXPR bool empty() const Q_DECL_NOTHROW { return size() == 0; }
+ Q_DECL_CONSTEXPR QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
+ Q_DECL_CONSTEXPR QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
+
+ //
+ // Qt compatibility API:
+ //
+ Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !m_data; }
+ Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return empty(); }
+ Q_DECL_CONSTEXPR int length() const /* not nothrow! */
+ { return Q_ASSERT(int(size()) == size()), int(size()); }
+ Q_DECL_CONSTEXPR QChar first() const { return front(); }
+ Q_DECL_CONSTEXPR QChar last() const { return back(); }
+private:
+ size_type m_size;
+ const storage_type *m_data;
+};
+Q_DECLARE_TYPEINFO(QStringView, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+#endif /* QSTRINGVIEW_H */
diff --git a/src/corelib/tools/qtimezoneprivate_icu.cpp b/src/corelib/tools/qtimezoneprivate_icu.cpp
index 887486f567..a07b2593b9 100644
--- a/src/corelib/tools/qtimezoneprivate_icu.cpp
+++ b/src/corelib/tools/qtimezoneprivate_icu.cpp
@@ -477,9 +477,10 @@ QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds() const
QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
{
- QByteArray regionCode = QLocalePrivate::countryToCode(country).toUtf8();
+ const QLatin1String regionCode = QLocalePrivate::countryToCode(country);
+ const QByteArray regionCodeUtf8 = QString(regionCode).toUtf8();
UErrorCode status = U_ZERO_ERROR;
- UEnumeration *uenum = ucal_openCountryTimeZones(regionCode, &status);
+ UEnumeration *uenum = ucal_openCountryTimeZones(regionCodeUtf8.data(), &status);
QList<QByteArray> result;
if (U_SUCCESS(status))
result = uenumToIdList(uenum);
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index 16dfaefb74..c6d59be3d8 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -386,7 +386,7 @@ static QLocale::Country userCountry()
const GEOID id = GetUserGeoID(GEOCLASS_NATION);
wchar_t code[3];
const int size = GetGeoInfo(id, GEO_ISO2, code, 3, 0);
- return (size == 3) ? QLocalePrivate::codeToCountry(reinterpret_cast<const QChar*>(code), size)
+ return (size == 3) ? QLocalePrivate::codeToCountry(QStringView(code, size))
: QLocale::AnyCountry;
}
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index d99eebd4b9..9879d55967 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -56,9 +56,6 @@
QT_BEGIN_NAMESPACE
-template<class T, int Prealloc>
-class QPodList;
-
// Prealloc = 256 by default, specified in qcontainerfwd.h
template<class T, int Prealloc>
class QVarLengthArray
@@ -236,7 +233,6 @@ public:
inline const T &back() const { return last(); }
private:
- friend class QPodList<T, Prealloc>;
void realloc(int size, int alloc);
int a; // capacity
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index b93ec824ed..8dd3550617 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -39,7 +39,6 @@ HEADERS += \
tools/qmargins.h \
tools/qmessageauthenticationcode.h \
tools/qcontiguouscache.h \
- tools/qpodlist_p.h \
tools/qpair.h \
tools/qpoint.h \
tools/qqueue.h \
@@ -63,6 +62,7 @@ HEADERS += \
tools/qstringiterator_p.h \
tools/qstringlist.h \
tools/qstringmatcher.h \
+ tools/qstringview.h \
tools/qtextboundaryfinder.h \
tools/qtimeline.h \
tools/qtools_p.h \
@@ -107,6 +107,7 @@ SOURCES += \
tools/qstring.cpp \
tools/qstringbuilder.cpp \
tools/qstringlist.cpp \
+ tools/qstringview.cpp \
tools/qtextboundaryfinder.cpp \
tools/qtimeline.cpp \
tools/qunicodetools.cpp \
diff --git a/src/gui/configure.json b/src/gui/configure.json
index fdbb6a4620..91e6bebc7f 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -38,6 +38,7 @@
"qpa-platform-guard": "boolean",
"sm": { "type": "boolean", "name": "sessionmanager" },
"tslib": "boolean",
+ "vulkan": "boolean",
"xcb": { "type": "enum", "values": [ "no", "yes", "qt", "system" ] },
"xcb-xlib": "boolean",
"xinput2": "boolean",
@@ -212,6 +213,14 @@
"-lts"
]
},
+ "vulkan": {
+ "label": "Vulkan",
+ "test": "qpa/vulkan",
+ "sources": [
+ { "type": "pkgConfig", "args": "vulkan" },
+ { "type": "makeSpec", "spec": "VULKAN" }
+ ]
+ },
"wayland_server": {
"label": "Wayland Server",
"test": "qpa/wayland-server",
@@ -599,6 +608,11 @@
"condition": "features.opengl-desktop || features.opengl-dynamic || features.opengles2",
"output": [ "publicFeature", "feature" ]
},
+ "vulkan": {
+ "label": "Vulkan",
+ "condition": "libs.vulkan",
+ "output": [ "publicFeature" ]
+ },
"openvg": {
"label": "OpenVG",
"condition": "libs.openvg",
@@ -1086,6 +1100,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"opengles31"
]
},
+ "vulkan",
"sessionmanager"
]
},
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 511cfd1d22..0682fd2274 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -46,6 +46,7 @@ include(math3d/math3d.pri)
include(opengl/opengl.pri)
include(animation/animation.pri)
include(itemmodels/itemmodels.pri)
+include(vulkan/vulkan.pri)
QMAKE_LIBS += $$QMAKE_LIBS_GUI
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index d72c05a3c5..1d700446a9 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -609,18 +609,18 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int icon
return INT_MAX;
}
-QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int scale)
+QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QThemeIconInfo &info, const QSize &size, int scale)
{
int iconsize = qMin(size.width(), size.height());
// Note that m_info.entries are sorted so that png-files
// come first
- const int numEntries = m_info.entries.size();
+ const int numEntries = info.entries.size();
// Search for exact matches first
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ QIconLoaderEngineEntry *entry = info.entries.at(i);
if (directoryMatchesSize(entry->dir, iconsize, scale)) {
return entry;
}
@@ -630,7 +630,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int s
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = 0;
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ QIconLoaderEngineEntry *entry = info.entries.at(i);
int distance = directorySizeDistance(entry->dir, iconsize, scale);
if (distance < minimalSize) {
minimalSize = distance;
@@ -651,7 +651,7 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
{
ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry) {
const QIconDirInfo &dir = entry->dir;
if (dir.type == QIconDirInfo::Scalable)
@@ -715,7 +715,7 @@ QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
{
ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry)
return entry->pixmap(size, mode, state);
@@ -764,7 +764,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast<QIconEngine::ScaledPixmapArgument*>(data);
// QIcon::pixmap() multiplies size by the device pixel ratio.
const int integerScale = qCeil(arg.scale);
- QIconLoaderEngineEntry *entry = entryForSize(arg.size / integerScale, integerScale);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, arg.size / integerScale, integerScale);
arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap();
}
break;
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 5f3a3ef948..9398bca585 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -132,12 +132,13 @@ public:
bool read(QDataStream &in) Q_DECL_OVERRIDE;
bool write(QDataStream &out) const Q_DECL_OVERRIDE;
+ Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1);
+
private:
QString key() const Q_DECL_OVERRIDE;
bool hasIcon() const;
void ensureLoaded();
void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- QIconLoaderEngineEntry *entryForSize(const QSize &size, int scale = 1);
QIconLoaderEngine(const QIconLoaderEngine &other);
QThemeIconInfo m_info;
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 2f25f4dcbc..55c3a4704a 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -564,6 +564,16 @@ bool QImageReaderPrivate::initHandler()
// probe the file extension
if (deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly) && autoDetectImageFormat) {
+ Q_ASSERT(qobject_cast<QFile*>(device) != 0); // future-proofing; for now this should always be the case, so...
+ QFile *file = static_cast<QFile *>(device);
+
+ if (file->error() == QFileDevice::ResourceError) {
+ // this is bad. we should abort the open attempt and note the failure.
+ imageReaderError = QImageReader::DeviceError;
+ errorString = file->errorString();
+ return false;
+ }
+
QList<QByteArray> extensions = QImageReader::supportedImageFormats();
if (!format.isEmpty()) {
// Try the most probable extension first
@@ -574,7 +584,6 @@ bool QImageReaderPrivate::initHandler()
int currentExtension = 0;
- QFile *file = static_cast<QFile *>(device);
QString fileName = file->fileName();
do {
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index ab15d8ee29..a39d204677 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -87,6 +87,9 @@
\value UnsupportedFormatError Qt does not support the requested
image format.
+ \value InvalidImageError An attempt was made to write an invalid QImage. An
+ example of an invalid image would be a null QImage.
+
\value UnknownError An unknown error occurred. If you get this
value after calling write(), it is most likely caused by a bug in
QImageWriter.
@@ -736,6 +739,13 @@ extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orie
*/
bool QImageWriter::write(const QImage &image)
{
+ // Do this before canWrite, so it doesn't create a file if this fails.
+ if (Q_UNLIKELY(image.isNull())) {
+ d->imageWriterError = QImageWriter::InvalidImageError;
+ d->errorString = QImageWriter::tr("Image is empty");
+ return false;
+ }
+
if (!canWrite())
return false;
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 58f8c51472..fd1fdd07e8 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -60,7 +60,8 @@ public:
enum ImageWriterError {
UnknownError,
DeviceError,
- UnsupportedFormatError
+ UnsupportedFormatError,
+ InvalidImageError
};
QImageWriter();
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 0aa05a04e2..5b3e3985a7 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -596,44 +596,7 @@ void QPixmap::setMask(const QBitmap &mask)
return;
detach();
-
- QImage image = data->toImage();
- if (mask.size().isEmpty()) {
- if (image.depth() != 1) { // hw: ????
- image = image.convertToFormat(QImage::Format_RGB32);
- }
- } else {
- const int w = image.width();
- const int h = image.height();
-
- switch (image.depth()) {
- case 1: {
- const QImage imageMask = mask.toImage().convertToFormat(image.format());
- for (int y = 0; y < h; ++y) {
- const uchar *mscan = imageMask.scanLine(y);
- uchar *tscan = image.scanLine(y);
- int bytesPerLine = image.bytesPerLine();
- for (int i = 0; i < bytesPerLine; ++i)
- tscan[i] &= mscan[i];
- }
- break;
- }
- default: {
- const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
- image = 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);
- for (int x = 0; x < w; ++x) {
- if (!(mscan[x>>3] & (1 << (x&7))))
- tscan[x] = 0;
- }
- }
- break;
- }
- }
- }
- data->fromImage(image, Qt::AutoColor);
+ data->setMask(mask);
}
/*!
@@ -1496,37 +1459,7 @@ QPaintEngine *QPixmap::paintEngine() const
*/
QBitmap QPixmap::mask() const
{
- if (!data || !hasAlphaChannel())
- return QBitmap();
-
- const 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 int w = image.width();
- const int h = image.height();
-
- QImage mask(w, h, QImage::Format_MonoLSB);
- if (mask.isNull()) // allocation failed
- return QBitmap();
-
- mask.setColorCount(2);
- mask.setColor(0, QColor(Qt::color0).rgba());
- mask.setColor(1, QColor(Qt::color1).rgba());
-
- const int bpl = mask.bytesPerLine();
-
- for (int y = 0; y < h; ++y) {
- const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
- uchar *dest = mask.scanLine(y);
- memset(dest, 0, bpl);
- for (int x = 0; x < w; ++x) {
- if (qAlpha(*src) > 0)
- dest[x >> 3] |= (1 << (x & 7));
- ++src;
- }
- }
-
- return QBitmap::fromImage(mask);
+ return data ? data->mask() : QBitmap();
}
/*!
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index 00c21a5f54..b123afb4db 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -160,6 +160,82 @@ bool QPlatformPixmap::scroll(int dx, int dy, const QRect &rect)
return false;
}
+QBitmap QPlatformPixmap::mask() const
+{
+ if (!hasAlphaChannel())
+ return QBitmap();
+
+ const 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 int w = image.width();
+ const int h = image.height();
+
+ QImage mask(w, h, QImage::Format_MonoLSB);
+ if (mask.isNull()) // allocation failed
+ return QBitmap();
+
+ mask.setColorCount(2);
+ mask.setColor(0, QColor(Qt::color0).rgba());
+ mask.setColor(1, QColor(Qt::color1).rgba());
+
+ const int bpl = mask.bytesPerLine();
+
+ for (int y = 0; y < h; ++y) {
+ const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
+ uchar *dest = mask.scanLine(y);
+ memset(dest, 0, bpl);
+ for (int x = 0; x < w; ++x) {
+ if (qAlpha(*src) > 0)
+ dest[x >> 3] |= (1 << (x & 7));
+ ++src;
+ }
+ }
+
+ return QBitmap::fromImage(mask);
+}
+
+void QPlatformPixmap::setMask(const QBitmap &mask)
+{
+ QImage image = toImage();
+ if (mask.size().isEmpty()) {
+ if (image.depth() != 1) { // hw: ????
+ image = image.convertToFormat(QImage::Format_RGB32);
+ }
+ } else {
+ const int w = image.width();
+ const int h = image.height();
+
+ switch (image.depth()) {
+ case 1: {
+ const QImage imageMask = mask.toImage().convertToFormat(image.format());
+ for (int y = 0; y < h; ++y) {
+ const uchar *mscan = imageMask.scanLine(y);
+ uchar *tscan = image.scanLine(y);
+ int bytesPerLine = image.bytesPerLine();
+ for (int i = 0; i < bytesPerLine; ++i)
+ tscan[i] &= mscan[i];
+ }
+ break;
+ }
+ default: {
+ const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
+ image = 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);
+ for (int x = 0; x < w; ++x) {
+ if (!(mscan[x>>3] & (1 << (x&7))))
+ tscan[x] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+ fromImage(image, Qt::AutoColor);
+}
+
QPixmap QPlatformPixmap::transformed(const QTransform &matrix,
Qt::TransformationMode mode) const
{
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 8513755cca..1857856b07 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -99,6 +99,9 @@ public:
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
+ virtual QBitmap mask() const;
+ virtual void setMask(const QBitmap &mask);
+
virtual bool hasAlphaChannel() const = 0;
virtual QPixmap transformed(const QTransform &matrix,
Qt::TransformationMode mode) const;
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index b7035d47c4..8ae9085d9f 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -471,6 +471,54 @@ QCursor::QCursor(Qt::CursorShape shape)
setShape(shape);
}
+/*!
+ \fn bool operator==(const QCursor &lhs, const QCursor &rhs)
+ \relates QCursor
+ \since 5.10
+
+ Equality operator. Returns \c true if \a lhs and \a rhs
+ have the same \l{QCursor::}{shape()} and, in the case of
+ \l{Qt::BitmapCursor}{bitmap cursors}, the same \l{QCursor::}{hotSpot()}
+ and either the same \l{QCursor::}{pixmap()} or the same
+ \l{QCursor::}{bitmap()} and \l{QCursor::}{mask()}.
+
+ \note When comparing bitmap cursors, this function only
+ compares the bitmaps' \l{QPixmap::cacheKey()}{cache keys},
+ not each pixel.
+
+ \sa operator!=(const QCursor &lhs, const QCursor &rhs)
+*/
+bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW
+{
+ if (lhs.d == rhs.d)
+ return true; // Copy or same shape
+
+ // Check pixmaps or bitmaps cache keys. Notice that having BitmapCursor
+ // shape implies either non-null pixmap or non-null bitmap and mask
+ if (lhs.shape() == Qt::BitmapCursor && rhs.shape() == Qt::BitmapCursor
+ && lhs.hotSpot() == rhs.hotSpot()) {
+ if (!lhs.d->pixmap.isNull())
+ return lhs.d->pixmap.cacheKey() == rhs.d->pixmap.cacheKey();
+
+ if (!rhs.d->pixmap.isNull())
+ return false;
+
+ return lhs.d->bm->cacheKey() == rhs.d->bm->cacheKey()
+ && lhs.d->bmm->cacheKey() == rhs.d->bmm->cacheKey();
+ }
+
+ return false;
+}
+
+/*!
+ \fn bool operator!=(const QCursor &lhs, const QCursor &rhs)
+ \relates QCursor
+ \since 5.10
+
+ Inequality operator. Returns the equivalent of !(\a lhs == \a rhs).
+
+ \sa operator==(const QCursor &lhs, const QCursor &rhs)
+*/
/*!
Returns the cursor shape identifier. The return value is one of
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index c7e9188e5b..ccce3d84ef 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -112,10 +112,14 @@ public:
inline static void setPos(QScreen *screen, const QPoint &p) { setPos(screen, p.x(), p.y()); }
private:
+ friend Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW;
QCursorData *d;
};
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QCursor)
+Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW;
+inline bool operator!=(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
+
/*****************************************************************************
QCursor stream functions
*****************************************************************************/
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index a59612474b..3af7f5c181 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -71,14 +71,11 @@ QDragManager *QDragManager::m_instance = 0;
QDragManager::QDragManager()
- : QObject(qApp), m_platformDropData(0), m_currentDropTarget(0),
+ : QObject(qApp), m_currentDropTarget(0),
m_platformDrag(QGuiApplicationPrivate::platformIntegration()->drag()),
m_object(0)
{
Q_ASSERT(!m_instance);
-
- if (m_platformDrag)
- m_platformDropData = m_platformDrag->platformDropData();
}
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index 6f2ec46252..eaf6c74fd4 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -134,7 +134,6 @@ public:
QObject *source() const;
private:
- QMimeData *m_platformDropData;
QObject *m_currentDropTarget;
QPlatformDrag *m_platformDrag;
QDrag *m_object;
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index a6bc7d4d9c..1a106be98b 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -56,7 +56,6 @@
#if defined(Q_OS_MACX)
#include <QtCore/private/qcore_mac_p.h>
-#include <Carbon/Carbon.h>
#endif
#include <algorithm>
@@ -70,6 +69,13 @@ struct MacSpecialKey {
ushort macSymbol;
};
+// 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 const int NumEntries = 21;
static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Escape, 0x238B },
diff --git a/src/gui/kernel/qplatformdrag.h b/src/gui/kernel/qplatformdrag.h
index 560f984a5b..54e6a667fe 100644
--- a/src/gui/kernel/qplatformdrag.h
+++ b/src/gui/kernel/qplatformdrag.h
@@ -95,7 +95,6 @@ public:
virtual ~QPlatformDrag();
QDrag *currentDrag() const;
- virtual QMimeData *platformDropData() = 0;
virtual Qt::DropAction drag(QDrag *m_drag) = 0;
virtual void cancelDrag();
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index fe1861e08b..873ec3a33b 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -237,6 +237,10 @@ QPlatformServices *QPlatformIntegration::services() const
is required to have this capability.
\value ApplicationIcon The platform supports setting the application icon. (since 5.5)
+
+ \value TopStackedNativeChildWindows The platform supports native child windows via
+ QWindowContainer without having to punch a transparent hole in the
+ backingstore. (since 5.10)
*/
/*!
@@ -260,7 +264,8 @@ QPlatformServices *QPlatformIntegration::services() const
bool QPlatformIntegration::hasCapability(Capability cap) const
{
- return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement;
+ return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement
+ || cap == TopStackedNativeChildWindows;
}
QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
@@ -387,6 +392,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return false;
case ShowIsMaximized:
return false;
+ case ShowShortcutsInContextMenus:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::ShowShortcutsInContextMenus);
case PasswordMaskDelay:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::PasswordMaskDelay);
case PasswordMaskCharacter:
@@ -622,4 +629,26 @@ void QPlatformIntegration::setApplicationIcon(const QIcon &icon) const
Q_UNUSED(icon);
}
+#if QT_CONFIG(vulkan)
+
+/*!
+ Factory function for QPlatformVulkanInstance. The \a instance parameter is a
+ pointer to the instance for which a platform-specific backend needs to be
+ created.
+
+ Returns a pointer to a QPlatformOpenGLContext instance or \c NULL if the context could
+ not be created.
+
+ \sa QVulkanInstance
+ \since 5.10
+*/
+QPlatformVulkanInstance *QPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ Q_UNUSED(instance);
+ qWarning("This plugin does not support createPlatformVulkanInstance");
+ return nullptr;
+}
+
+#endif // QT_CONFIG(vulkan)
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 0449e0b4c8..eeaa7574f7 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -78,6 +78,8 @@ class QPlatformSessionManager;
class QKeyEvent;
class QPlatformOffscreenSurface;
class QOffscreenSurface;
+class QPlatformVulkanInstance;
+class QVulkanInstance;
class Q_GUI_EXPORT QPlatformIntegration
{
@@ -99,7 +101,8 @@ public:
RasterGLSurface,
AllGLFunctionsQueryable,
ApplicationIcon,
- SwitchableWidgetComposition
+ SwitchableWidgetComposition,
+ TopStackedNativeChildWindows
};
virtual ~QPlatformIntegration() { }
@@ -160,6 +163,7 @@ public:
ItemViewActivateItemOnSingleClick,
UiEffects,
WheelScrollLines,
+ ShowShortcutsInContextMenus,
};
virtual QVariant styleHint(StyleHint hint) const;
@@ -188,6 +192,10 @@ public:
virtual void beep() const;
+#if QT_CONFIG(vulkan)
+ virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const;
+#endif
+
protected:
void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
void destroyScreen(QPlatformScreen *screen);
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 878f656f2e..ebf65eda12 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -161,6 +161,8 @@ QT_BEGIN_NAMESPACE
The default value is double the MouseDoubleClickDistance, or 10 logical pixels
if that is not specified.
+ \value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus.
+
\sa themeHint(), QStyle::pixelMetric()
*/
@@ -516,6 +518,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
return QVariant(QStringList());
case QPlatformTheme::StyleNames:
return QVariant(QStringList());
+ case QPlatformTheme::ShowShortcutsInContextMenus:
+ return QVariant(false);
case TextCursorWidth:
return QVariant(1);
case DropShadow:
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 2ba2f8669f..f4ff418db6 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -115,7 +115,8 @@ public:
MousePressAndHoldInterval,
MouseDoubleClickDistance,
WheelScrollLines,
- TouchDoubleTapDistance
+ TouchDoubleTapDistance,
+ ShowShortcutsInContextMenus
};
enum DialogType {
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 5062bd1e77..dda7cc94fe 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -261,7 +261,7 @@ QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const
Qt::WindowActive can be ignored.
*/
-void QPlatformWindow::setWindowState(Qt::WindowState)
+void QPlatformWindow::setWindowState(Qt::WindowStates)
{
}
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 8af8791bb4..eead96f2d1 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -89,7 +89,7 @@ public:
virtual void setVisible(bool visible);
virtual void setWindowFlags(Qt::WindowFlags flags);
- virtual void setWindowState(Qt::WindowState state);
+ virtual void setWindowState(Qt::WindowStates state);
virtual WId winId() const;
virtual void setParent(const QPlatformWindow *window);
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index fc62273325..481971f21a 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -353,13 +353,6 @@ QSimpleDrag::QSimpleDrag() : m_current_window(0)
{
}
-QMimeData *QSimpleDrag::platformDropData()
-{
- if (drag())
- return drag()->mimeData();
- return 0;
-}
-
void QSimpleDrag::startDrag()
{
QBasicDrag::startDrag();
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h
index 0b8a0bc703..45c13e43b2 100644
--- a/src/gui/kernel/qsimpledrag_p.h
+++ b/src/gui/kernel/qsimpledrag_p.h
@@ -125,7 +125,6 @@ class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag
{
public:
QSimpleDrag();
- virtual QMimeData *platformDropData() Q_DECL_OVERRIDE;
protected:
virtual void startDrag() Q_DECL_OVERRIDE;
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 85c0768e35..0850228ee5 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -365,6 +365,17 @@ bool QStyleHints::showIsMaximized() const
}
/*!
+ \property QStyleHints::showShortcutsInContextMenus
+ \since 5.10
+ \brief \c true if the platform normally shows shortcut key sequences in
+ context menus, otherwise \c false.
+*/
+bool QStyleHints::showShortcutsInContextMenus() const
+{
+ return themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
+}
+
+/*!
\property QStyleHints::passwordMaskDelay
\brief the time, in milliseconds, a typed letter is displayed unshrouded
in a text input field in password mode.
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index b9bf428edd..3230149247 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -90,6 +90,7 @@ public:
int cursorFlashTime() const;
bool showIsFullScreen() const;
bool showIsMaximized() const;
+ bool showShortcutsInContextMenus() const;
int passwordMaskDelay() const;
QChar passwordMaskCharacter() const;
qreal fontSmoothingGamma() const;
diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp
index 3cdd11de8c..63651ee822 100644
--- a/src/gui/kernel/qsurface.cpp
+++ b/src/gui/kernel/qsurface.cpp
@@ -78,6 +78,8 @@ QT_BEGIN_NAMESPACE
requires the use of private API.
\value OpenVGSurface The surface is an OpenVG compatible surface and can be used
in conjunction with OpenVG contexts.
+ \value VulkanSurface The surface is a Vulkan compatible surface and can be used
+ in conjunction with the Vulkan graphics API.
*/
diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h
index a96b7a6422..7e09449d12 100644
--- a/src/gui/kernel/qsurface.h
+++ b/src/gui/kernel/qsurface.h
@@ -66,6 +66,7 @@ public:
OpenGLSurface,
RasterGLSurface,
OpenVGSurface,
+ VulkanSurface
};
virtual ~QSurface();
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
index 000d727380..574310f554 100644
--- a/src/gui/kernel/qsurfaceformat.cpp
+++ b/src/gui/kernel/qsurfaceformat.cpp
@@ -73,6 +73,7 @@ public:
, major(2)
, minor(0)
, swapInterval(1) // default to vsync
+ , colorSpace(QSurfaceFormat::DefaultColorSpace)
{
}
@@ -91,7 +92,8 @@ public:
profile(other->profile),
major(other->major),
minor(other->minor),
- swapInterval(other->swapInterval)
+ swapInterval(other->swapInterval),
+ colorSpace(other->colorSpace)
{
}
@@ -110,6 +112,7 @@ public:
int major;
int minor;
int swapInterval;
+ QSurfaceFormat::ColorSpace colorSpace;
};
/*!
@@ -124,6 +127,12 @@ public:
contains surface configuration parameters such as OpenGL profile and
version for rendering, whether or not to enable stereo buffers, and swap
behaviour.
+
+ \note When troubleshooting context or window format issues, it can be
+ helpful to enable the logging category \c{qt.qpa.gl}. Depending on the
+ platform, this may print useful debug information when it comes to OpenGL
+ initialization and the native visual or framebuffer configurations which
+ QSurfaceFormat gets mapped to.
*/
/*!
@@ -199,6 +208,22 @@ public:
*/
/*!
+ \enum QSurfaceFormat::ColorSpace
+
+ This enum is used to specify the preferred color space, controlling if the
+ window's associated default framebuffer is able to do updates and blending
+ in a given encoding instead of the standard linear operations.
+
+ \value DefaultColorSpace The default, unspecified color space.
+
+ \value sRGBColorSpace When \c{GL_ARB_framebuffer_sRGB} or
+ \c{GL_EXT_framebuffer_sRGB} is supported by the platform and this value is
+ set, the window will be created with an sRGB-capable default
+ framebuffer. Note that some platforms may return windows with a sRGB-capable
+ default framebuffer even when not requested explicitly.
+ */
+
+/*!
Constructs a default initialized QSurfaceFormat.
\note By default OpenGL 2.0 is requested since this provides the highest
@@ -736,6 +761,47 @@ int QSurfaceFormat::swapInterval() const
return d->swapInterval;
}
+/*!
+ Sets the preferred \a colorSpace.
+
+ For example, this allows requesting windows with default framebuffers that
+ are sRGB-capable on platforms that support it.
+
+ \note When the requested color space is not supported by the platform, the
+ request is ignored. Query the QSurfaceFormat after window creation to verify
+ if the color space request could be honored or not.
+
+ \note This setting controls if the default framebuffer of the window is
+ capable of updates and blending in a given color space. It does not change
+ applications' output by itself. The applications' rendering code will still
+ have to opt in via the appropriate OpenGL calls to enable updates and
+ blending to be performed in the given color space instead of using the
+ standard linear operations.
+
+ \since 5.10
+
+ \sa colorSpace()
+ */
+void QSurfaceFormat::setColorSpace(ColorSpace colorSpace)
+{
+ if (d->colorSpace != colorSpace) {
+ detach();
+ d->colorSpace = colorSpace;
+ }
+}
+
+/*!
+ \return the color space.
+
+ \since 5.10
+
+ \sa setColorSpace()
+*/
+QSurfaceFormat::ColorSpace QSurfaceFormat::colorSpace() const
+{
+ return d->colorSpace;
+}
+
Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format)
/*!
@@ -841,6 +907,7 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f)
<< ", samples " << d->numSamples
<< ", swapBehavior " << d->swapBehavior
<< ", swapInterval " << d->swapInterval
+ << ", colorSpace " << d->colorSpace
<< ", profile " << d->profile
<< ')';
diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h
index 246163609e..ed63eb8bbf 100644
--- a/src/gui/kernel/qsurfaceformat.h
+++ b/src/gui/kernel/qsurfaceformat.h
@@ -85,6 +85,12 @@ public:
};
Q_ENUM(OpenGLContextProfile)
+ enum ColorSpace {
+ DefaultColorSpace,
+ sRGBColorSpace
+ };
+ Q_ENUM(ColorSpace)
+
QSurfaceFormat();
/*implicit*/ QSurfaceFormat(FormatOptions options);
QSurfaceFormat(const QSurfaceFormat &other);
@@ -145,6 +151,9 @@ public:
int swapInterval() const;
void setSwapInterval(int interval);
+ ColorSpace colorSpace() const;
+ void setColorSpace(ColorSpace colorSpace);
+
static void setDefaultFormat(const QSurfaceFormat &format);
static QSurfaceFormat defaultFormat();
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index d44bfabc04..3f5f71002b 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
application, isExposed() will simply return the same value as isVisible().
QWindow::Visibility queried through visibility() is a convenience API
- combining the functions of visible() and windowState().
+ combining the functions of visible() and windowStates().
\section1 Rendering
@@ -323,27 +323,16 @@ void QWindowPrivate::updateVisibility()
QWindow::Visibility old = visibility;
- if (visible) {
- switch (windowState) {
- case Qt::WindowMinimized:
- visibility = QWindow::Minimized;
- break;
- case Qt::WindowMaximized:
- visibility = QWindow::Maximized;
- break;
- case Qt::WindowFullScreen:
- visibility = QWindow::FullScreen;
- break;
- case Qt::WindowNoState:
- visibility = QWindow::Windowed;
- break;
- default:
- Q_ASSERT(false);
- break;
- }
- } else {
+ if (!visible)
visibility = QWindow::Hidden;
- }
+ else if (windowState & Qt::WindowMinimized)
+ visibility = QWindow::Minimized;
+ else if (windowState & Qt::WindowFullScreen)
+ visibility = QWindow::FullScreen;
+ else if (windowState & Qt::WindowMaximized)
+ visibility = QWindow::Maximized;
+ else
+ visibility = QWindow::Windowed;
if (visibility != old)
emit q->visibilityChanged(visibility);
@@ -1216,6 +1205,17 @@ qreal QWindow::devicePixelRatio() const
return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
}
+Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
+{
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+}
+
/*!
\brief set the screen-occupation state of the window
@@ -1224,31 +1224,69 @@ qreal QWindow::devicePixelRatio() const
The enum value Qt::WindowActive is not an accepted parameter.
- \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
+ \sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates()
*/
void QWindow::setWindowState(Qt::WindowState state)
{
- if (state == Qt::WindowActive) {
- qWarning("QWindow::setWindowState does not accept Qt::WindowActive");
- return;
- }
+ setWindowStates(state);
+}
+/*!
+ \brief set the screen-occupation state of the window
+ \since 5.10
+
+ The window \a state represents whether the window appears in the
+ windowing system as maximized, minimized and/or fullscreen.
+
+ The window can be in a combination of several states. For example, if
+ the window is both minimized and maximized, the window will appear
+ minimized, but clicking on the task bar entry will restore it to the
+ maximized state.
+
+ The enum value Qt::WindowActive should not be set.
+
+ \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
+ */
+void QWindow::setWindowStates(Qt::WindowStates state)
+{
Q_D(QWindow);
+ if (state & Qt::WindowActive) {
+ qWarning("QWindow::setWindowStates does not accept Qt::WindowActive");
+ state &= ~Qt::WindowActive;
+ }
+
if (d->platformWindow)
d->platformWindow->setWindowState(state);
d->windowState = state;
- emit windowStateChanged(d->windowState);
+ emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
}
/*!
\brief the screen-occupation state of the window
- \sa setWindowState()
+ \sa setWindowState(), windowStates()
*/
Qt::WindowState QWindow::windowState() const
{
Q_D(const QWindow);
+ return QWindowPrivate::effectiveState(d->windowState);
+}
+
+/*!
+ \brief the screen-occupation state of the window
+ \since 5.10
+
+ The window can be in a combination of several states. For example, if
+ the window is both minimized and maximized, the window will appear
+ minimized, but clicking on the task bar entry will restore it to
+ the maximized state.
+
+ \sa setWindowStates()
+*/
+Qt::WindowStates QWindow::windowStates() const
+{
+ Q_D(const QWindow);
return d->windowState;
}
@@ -1256,7 +1294,7 @@ Qt::WindowState QWindow::windowState() const
\fn QWindow::windowStateChanged(Qt::WindowState windowState)
This signal is emitted when the \a windowState changes, either
- by being set explicitly with setWindowState(), or automatically when
+ by being set explicitly with setWindowStates(), or automatically when
the user clicks one of the titlebar buttons or by other means.
*/
@@ -1997,42 +2035,42 @@ void QWindow::hide()
/*!
Shows the window as minimized.
- Equivalent to calling setWindowState(Qt::WindowMinimized) and then
+ Equivalent to calling setWindowStates(Qt::WindowMinimized) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showMinimized()
{
- setWindowState(Qt::WindowMinimized);
+ setWindowStates(Qt::WindowMinimized);
setVisible(true);
}
/*!
Shows the window as maximized.
- Equivalent to calling setWindowState(Qt::WindowMaximized) and then
+ Equivalent to calling setWindowStates(Qt::WindowMaximized) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showMaximized()
{
- setWindowState(Qt::WindowMaximized);
+ setWindowStates(Qt::WindowMaximized);
setVisible(true);
}
/*!
Shows the window as fullscreen.
- Equivalent to calling setWindowState(Qt::WindowFullScreen) and then
+ Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showFullScreen()
{
- setWindowState(Qt::WindowFullScreen);
+ setWindowStates(Qt::WindowFullScreen);
setVisible(true);
#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
// activating it here before libscreen activates it causes problems
@@ -2043,14 +2081,14 @@ void QWindow::showFullScreen()
/*!
Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
- Equivalent to calling setWindowState(Qt::WindowNoState) and then
+ Equivalent to calling setWindowStates(Qt::WindowNoState) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showNormal()
{
- setWindowState(Qt::WindowNoState);
+ setWindowStates(Qt::WindowNoState);
setVisible(true);
}
@@ -2246,7 +2284,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::WindowStateChange: {
Q_D(QWindow);
- emit windowStateChanged(d->windowState);
+ emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
break;
}
@@ -2762,6 +2800,30 @@ QDebug operator<<(QDebug debug, const QWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
+#if QT_CONFIG(vulkan)
+
+/*!
+ Associates this window with the specified Vulkan \a instance.
+
+ \a instance must stay valid as long as this QWindow instance exists.
+ */
+void QWindow::setVulkanInstance(QVulkanInstance *instance)
+{
+ Q_D(QWindow);
+ d->vulkanInstance = instance;
+}
+
+/*!
+ \return the associrated Vulkan instance or \c null if there is none.
+ */
+QVulkanInstance *QWindow::vulkanInstance() const
+{
+ Q_D(const QWindow);
+ return d->vulkanInstance;
+}
+
+#endif // QT_CONFIG(vulkan)
+
QT_END_NAMESPACE
#include "moc_qwindow.cpp"
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index 2883749d2e..529589e67b 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -88,6 +88,9 @@ class QWindowContainer;
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
#endif
+#if QT_CONFIG(vulkan)
+class QVulkanInstance;
+#endif
class Q_GUI_EXPORT QWindow : public QObject, public QSurface
{
@@ -189,7 +192,9 @@ public:
qreal devicePixelRatio() const;
Qt::WindowState windowState() const;
+ Qt::WindowStates windowStates() const;
void setWindowState(Qt::WindowState state);
+ void setWindowStates(Qt::WindowStates states);
void setTransientParent(QWindow *parent);
QWindow *transientParent() const;
@@ -267,6 +272,11 @@ public:
static QWindow *fromWinId(WId id);
+#if QT_CONFIG(vulkan)
+ void setVulkanInstance(QVulkanInstance *instance);
+ QVulkanInstance *vulkanInstance() const;
+#endif
+
public Q_SLOTS:
Q_REVISION(1) void requestActivate();
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index dd282a671d..cffe5b4125 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -105,6 +105,9 @@ public:
, hasCursor(false)
#endif
, compositing(false)
+#if QT_CONFIG(vulkan)
+ , vulkanInstance(nullptr)
+#endif
{
isWindow = true;
}
@@ -151,6 +154,8 @@ public:
static QWindowPrivate *get(QWindow *window) { return window->d_func(); }
+ static Qt::WindowState effectiveState(Qt::WindowStates);
+
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;
QWindow *parentWindow;
@@ -163,7 +168,7 @@ public:
QString windowFilePath;
QIcon windowIcon;
QRect geometry;
- Qt::WindowState windowState;
+ Qt::WindowStates windowState;
QWindow::Visibility visibility;
bool resizeEventPending;
bool receivedExpose;
@@ -194,6 +199,10 @@ public:
bool compositing;
QElapsedTimer lastComposeTime;
+
+#if QT_CONFIG(vulkan)
+ QVulkanInstance *vulkanInstance;
+#endif
};
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 7ad4f57198..f3486acbc3 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -241,14 +241,14 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::Fo
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowState newState, int oldState)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState)
{
Q_ASSERT(window);
if (oldState < Qt::WindowNoState)
oldState = window->windowState();
QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
- new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowState(oldState));
+ new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState));
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 253584314c..c9e34527cd 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -176,7 +176,7 @@ public:
static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState, int oldState = -1);
+ static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState = -1);
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 1bcc79552d..4ee85b98a1 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -168,13 +168,13 @@ public:
class WindowStateChangedEvent : public WindowSystemEvent {
public:
- WindowStateChangedEvent(QWindow *_window, Qt::WindowState _newState, Qt::WindowState _oldState)
+ WindowStateChangedEvent(QWindow *_window, Qt::WindowStates _newState, Qt::WindowStates _oldState)
: WindowSystemEvent(WindowStateChanged), window(_window), newState(_newState), oldState(_oldState)
{ }
QPointer<QWindow> window;
- Qt::WindowState newState;
- Qt::WindowState oldState;
+ Qt::WindowStates newState;
+ Qt::WindowStates oldState;
};
class WindowScreenChangedEvent : public WindowSystemEvent {
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 5c38648fe7..8c9d1e1c49 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -2657,6 +2657,241 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
return buffer;
}
+template<TextureBlendType blendType, QPixelLayout::BPP bpp>
+static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/)
+{
+ const QPixelLayout *layout = &qPixelLayouts[image.format];
+ const QVector<QRgb> *clut = image.colorTable;
+ Q_ASSERT(bpp == QPixelLayout::BPPNone || bpp == layout->bpp);
+ // When templated 'fetch' should be inlined at compile time:
+ const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : fetchPixels<bpp>;
+ const ConvertFunc convertToARGB32PM = layout->convertToARGB32PM;
+
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+
+ int disty = (fy & 0x0000ffff) >> 8;
+ int idisty = 256 - disty;
+ int x = fx >> 16;
+ int length = end - b;
+
+ // The idea is first to do the interpolation between the row s1 and the row s2
+ // into an intermediate buffer, then we interpolate between two pixel of this buffer.
+ // +1 for the last pixel to interpolate with, and +1 for rounding errors.
+ uint buf1[buffer_size + 2];
+ uint buf2[buffer_size + 2];
+ const uint *ptr1;
+ const uint *ptr2;
+
+ int count = (qint64(length) * fdx + fixed_scale - 1) / fixed_scale + 2;
+ Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
+
+ if (blendType == BlendTransformedBilinearTiled) {
+ x %= image.width;
+ if (x < 0)
+ x += image.width;
+ int len1 = qMin(count, image.width - x);
+ int len2 = qMin(x, count - len1);
+
+ ptr1 = fetch(buf1, s1, x, len1);
+ ptr1 = convertToARGB32PM(buf1, ptr1, len1, clut, 0);
+ ptr2 = fetch(buf2, s2, x, len1);
+ ptr2 = convertToARGB32PM(buf2, ptr2, len1, clut, 0);
+ for (int i = 0; i < len1; ++i) {
+ uint t = ptr1[i];
+ uint b = ptr2[i];
+ buf1[i] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ buf2[i] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ }
+
+ if (len2) {
+ ptr1 = fetch(buf1 + len1, s1, 0, len2);
+ ptr1 = convertToARGB32PM(buf1 + len1, ptr1, len2, clut, 0);
+ ptr2 = fetch(buf2 + len1, s2, 0, len2);
+ ptr2 = convertToARGB32PM(buf2 + len1, ptr2, len2, clut, 0);
+ for (int i = 0; i < len2; ++i) {
+ uint t = ptr1[i];
+ uint b = ptr2[i];
+ buf1[i + len1] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ }
+ }
+ for (int i = image.width; i < count; ++i) {
+ buf1[i] = buf1[i - image.width];
+ buf2[i] = buf2[i - image.width];
+ }
+ } else {
+ int start = qMax(x, image.x1);
+ int end = qMin(x + count, image.x2);
+ int len = qMax(1, end - start);
+ int leading = start - x;
+
+ ptr1 = fetch(buf1 + leading, s1, start, len);
+ ptr1 = convertToARGB32PM(buf1 + leading, ptr1, len, clut, 0);
+ ptr2 = fetch(buf2 + leading, s2, start, len);
+ ptr2 = convertToARGB32PM(buf2 + leading, ptr2, len, clut, 0);
+
+ for (int i = 0; i < len; ++i) {
+ uint t = ptr1[i];
+ uint b = ptr2[i];
+ buf1[i + leading] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ buf2[i + leading] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ }
+
+ for (int i = 0; i < leading; ++i) {
+ buf1[i] = buf1[leading];
+ buf2[i] = buf2[leading];
+ }
+ for (int i = leading + len; i < count; ++i) {
+ buf1[i] = buf1[i - 1];
+ buf2[i] = buf2[i - 1];
+ }
+ }
+
+ // Now interpolate the values from the intermediate_buffer to get the final result.
+ fx &= fixed_scale - 1;
+ Q_ASSERT((fx >> 16) == 0);
+ while (b < end) {
+ int x1 = (fx >> 16);
+ int x2 = x1 + 1;
+ Q_ASSERT(x1 >= 0);
+ Q_ASSERT(x2 < count);
+
+ int distx = (fx & 0x0000ffff) >> 8;
+ int idistx = 256 - distx;
+ int rb = ((buf1[x1] * idistx + buf1[x2] * distx) >> 8) & 0xff00ff;
+ int ag = (buf2[x1] * idistx + buf2[x2] * distx) & 0xff00ff00;
+ *b++ = rb | ag;
+ fx += fdx;
+ }
+}
+
+
+typedef void (QT_FASTCALL *BilinearFastTransformFetcher)(uint *buf1, uint *buf2, const int len, const QTextureData &image,
+ int fx, int fy, const int fdx, const int fdy);
+
+template<TextureBlendType blendType, QPixelLayout::BPP bpp>
+static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2, const int len, const QTextureData &image,
+ int fx, int fy, const int fdx, const int fdy)
+{
+ const QPixelLayout &layout = qPixelLayouts[image.format];
+ Q_ASSERT(bpp == QPixelLayout::BPPNone || bpp == layout.bpp);
+ // When templated 'fetch1' should be inlined at compile time:
+ const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout.bpp] : fetchPixel<bpp>;
+ if (fdy == 0) {
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+
+ int i = 0;
+ if (blendType == BlendTransformedBilinear) {
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ if (x1 != x2)
+ break;
+ buf1[i * 2 + 0] = buf1[i * 2 + 1] = fetch1(s1, x1);
+ buf2[i * 2 + 0] = buf2[i * 2 + 1] = fetch1(s2, x1);
+ fx += fdx;
+ }
+ int fastLen = len;
+ if (fdx > 0)
+ fastLen = qMin(fastLen, int((qint64(image.x2 - 1) * fixed_scale - fx) / fdx));
+ else if (fdx < 0)
+ fastLen = qMin(fastLen, int((qint64(image.x1) * fixed_scale - fx) / fdx));
+
+ for (; i < fastLen; ++i) {
+ int x = (fx >> 16);
+ buf1[i * 2 + 0] = fetch1(s1, x);
+ buf1[i * 2 + 1] = fetch1(s1, x + 1);
+ buf2[i * 2 + 0] = fetch1(s2, x);
+ buf2[i * 2 + 1] = fetch1(s2, x + 1);
+ fx += fdx;
+ }
+ }
+
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ buf1[i * 2 + 0] = fetch1(s1, x1);
+ buf1[i * 2 + 1] = fetch1(s1, x2);
+ buf2[i * 2 + 0] = fetch1(s2, x1);
+ buf2[i * 2 + 1] = fetch1(s2, x2);
+ fx += fdx;
+ }
+ } else {
+ int i = 0;
+ if (blendType == BlendTransformedBilinear) {
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+ if (x1 != x2 && y1 != y2)
+ break;
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+ buf1[i * 2 + 0] = fetch1(s1, x1);
+ buf1[i * 2 + 1] = fetch1(s1, x2);
+ buf2[i * 2 + 0] = fetch1(s2, x1);
+ buf2[i * 2 + 1] = fetch1(s2, x2);
+ fx += fdx;
+ fy += fdy;
+ }
+ int fastLen = len;
+ if (fdx > 0)
+ fastLen = qMin(fastLen, int((qint64(image.x2 - 1) * fixed_scale - fx) / fdx));
+ else if (fdx < 0)
+ fastLen = qMin(fastLen, int((qint64(image.x1) * fixed_scale - fx) / fdx));
+ if (fdy > 0)
+ fastLen = qMin(fastLen, int((qint64(image.y2 - 1) * fixed_scale - fy) / fdy));
+ else if (fdy < 0)
+ fastLen = qMin(fastLen, int((qint64(image.y1) * fixed_scale - fy) / fdy));
+
+ for (; i < fastLen; ++i) {
+ int x = (fx >> 16);
+ int y = (fy >> 16);
+ const uchar *s1 = image.scanLine(y);
+ const uchar *s2 = s1 + image.bytesPerLine;
+ buf1[i * 2 + 0] = fetch1(s1, x);
+ buf1[i * 2 + 1] = fetch1(s1, x + 1);
+ buf2[i * 2 + 0] = fetch1(s2, x);
+ buf2[i * 2 + 1] = fetch1(s2, x + 1);
+ fx += fdx;
+ fy += fdy;
+ }
+ }
+
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+ buf1[i * 2 + 0] = fetch1(s1, x1);
+ buf1[i * 2 + 1] = fetch1(s1, x2);
+ buf2[i * 2 + 0] = fetch1(s2, x1);
+ buf2[i * 2 + 1] = fetch1(s2, x2);
+ fx += fdx;
+ fy += fdy;
+ }
+ }
+}
+
// blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled
template<TextureBlendType blendType, QPixelLayout::BPP bpp>
static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *,
@@ -2664,19 +2899,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
{
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
const QVector<QRgb> *clut = data->texture.colorTable;
- if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1
- Q_ASSERT(layout->bpp == bpp);
- // When templated 'fetch' should be inlined at compile time:
- const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : FetchPixelsFunc(fetchPixels<bpp>);
- const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>);
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- int image_x1 = data->texture.x1;
- int image_y1 = data->texture.y1;
- int image_x2 = data->texture.x2 - 1;
- int image_y2 = data->texture.y2 - 1;
+ Q_ASSERT(bpp == QPixelLayout::BPPNone || layout->bpp == bpp);
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
@@ -2692,203 +2915,80 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
fx -= half_point;
fy -= half_point;
- if (fdy == 0) { //simple scale, no rotation
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
+ if (fdy == 0) { // simple scale, no rotation or shear
if (fdx <= fixed_scale && fdx > 0) { // scale up on X
- int disty = (fy & 0x0000ffff) >> 8;
- int idisty = 256 - disty;
- int x = fx >> 16;
-
- // The idea is first to do the interpolation between the row s1 and the row s2
- // into an intermediate buffer, then we interpolate between two pixel of this buffer.
- // +1 for the last pixel to interpolate with, and +1 for rounding errors.
- uint buf1[buffer_size + 2];
- uint buf2[buffer_size + 2];
- const uint *ptr1;
- const uint *ptr2;
-
- int count = (qint64(length) * fdx + fixed_scale - 1) / fixed_scale + 2;
- Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
-
- if (blendType == BlendTransformedBilinearTiled) {
- x %= image_width;
- if (x < 0)
- x += image_width;
- int len1 = qMin(count, image_width - x);
- int len2 = qMin(x, count - len1);
-
- ptr1 = fetch(buf1, s1, x, len1);
- ptr1 = layout->convertToARGB32PM(buf1, ptr1, len1, clut, 0);
- ptr2 = fetch(buf2, s2, x, len1);
- ptr2 = layout->convertToARGB32PM(buf2, ptr2, len1, clut, 0);
- for (int i = 0; i < len1; ++i) {
- uint t = ptr1[i];
- uint b = ptr2[i];
- buf1[i] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- buf2[i] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
- }
-
- if (len2) {
- ptr1 = fetch(buf1 + len1, s1, 0, len2);
- ptr1 = layout->convertToARGB32PM(buf1 + len1, ptr1, len2, clut, 0);
- ptr2 = fetch(buf2 + len1, s2, 0, len2);
- ptr2 = layout->convertToARGB32PM(buf2 + len1, ptr2, len2, clut, 0);
- for (int i = 0; i < len2; ++i) {
- uint t = ptr1[i];
- uint b = ptr2[i];
- buf1[i + len1] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
- }
- }
- for (int i = image_width; i < count; ++i) {
- buf1[i] = buf1[i - image_width];
- buf2[i] = buf2[i - image_width];
- }
- } else {
- int start = qMax(x, image_x1);
- int end = qMin(x + count, image_x2 + 1);
- int len = qMax(1, end - start);
- int leading = start - x;
-
- ptr1 = fetch(buf1 + leading, s1, start, len);
- ptr1 = layout->convertToARGB32PM(buf1 + leading, ptr1, len, clut, 0);
- ptr2 = fetch(buf2 + leading, s2, start, len);
- ptr2 = layout->convertToARGB32PM(buf2 + leading, ptr2, len, clut, 0);
-
- for (int i = 0; i < len; ++i) {
- uint t = ptr1[i];
- uint b = ptr2[i];
- buf1[i + leading] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- buf2[i + leading] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
- }
-
- for (int i = 0; i < leading; ++i) {
- buf1[i] = buf1[leading];
- buf2[i] = buf2[leading];
- }
- for (int i = leading + len; i < count; ++i) {
- buf1[i] = buf1[i - 1];
- buf2[i] = buf2[i - 1];
- }
- }
-
- // Now interpolate the values from the intermediate_buffer to get the final result.
- fx &= fixed_scale - 1;
- Q_ASSERT((fx >> 16) == 0);
- for (int i = 0; i < length; ++i) {
- int x1 = (fx >> 16);
- int x2 = x1 + 1;
- Q_ASSERT(x1 >= 0);
- Q_ASSERT(x2 < count);
-
- int distx = (fx & 0x0000ffff) >> 8;
- int idistx = 256 - distx;
- int rb = ((buf1[x1] * idistx + buf1[x2] * distx) >> 8) & 0xff00ff;
- int ag = (buf2[x1] * idistx + buf2[x2] * distx) & 0xff00ff00;
- buffer[i] = rb | ag;
- fx += fdx;
- }
+ fetchTransformedBilinear_simple_upscale_helper<blendType, bpp>(buffer, buffer + length, data->texture, fx, fy, fdx, fdy);
} else {
+ const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>;
+
uint buf1[buffer_size];
uint buf2[buffer_size];
uint *b = buffer;
while (length) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- for (int i = 0; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- buf1[i * 2 + 0] = fetch1(s1, x1);
- buf1[i * 2 + 1] = fetch1(s1, x2);
- buf2[i * 2 + 0] = fetch1(s2, x1);
- buf2[i * 2 + 1] = fetch1(s2, x2);
- fx += fdx;
- }
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, 0);
layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
if ((fdx < 0 && fdx > -(fixed_scale / 8)) || qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x
int disty = (fy & 0x0000ffff) >> 8;
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff) >> 8;
+ int distx = (fx & 0x0000ffff) >> 8;
b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty);
- fracX += fdx;
+ fx += fdx;
}
- } else { //scale down
+ } else {
int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
for (int i = 0; i < len; ++i) {
uint tl = buf1[i * 2 + 0];
uint tr = buf1[i * 2 + 1];
uint bl = buf2[i * 2 + 0];
uint br = buf2[i * 2 + 1];
- int distx = ((fracX & 0x0000ffff) + 0x0800) >> 12;
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
b[i] = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
- fracX += fdx;
+ fx += fdx;
}
}
length -= len;
b += len;
}
}
- } else { //rotation
+ } else { // rotation or shear
+ const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>;
+
uint buf1[buffer_size];
uint buf2[buffer_size];
uint *b = buffer;
-
while (length) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- int fracY = fy;
- for (int i = 0; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
-
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
- buf1[i * 2 + 0] = fetch1(s1, x1);
- buf1[i * 2 + 1] = fetch1(s1, x2);
- buf2[i * 2 + 0] = fetch1(s2, x1);
- buf2[i * 2 + 1] = fetch1(s2, x2);
- fx += fdx;
- fy += fdy;
- }
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, fdy);
layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
- if (qAbs(data->m11) < qreal(1./8.) || qAbs(data->m22) < qreal(1./8.) ) {
- //if we are zooming more than 8 times, we use 8bit precision for the position.
+ if (qAbs(data->m11) < qreal(1./8.)|| qAbs(data->m22) < qreal(1./8.)) {
+ // If we are zooming more than 8 times, we use 8bit precision for the position.
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff) >> 8;
- int disty = (fracY & 0x0000ffff) >> 8;
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty);
- fracX += fdx;
- fracY += fdy;
+ fx += fdx;
+ fy += fdy;
}
} else {
- //we are zooming less than 8x, use 4bit precision
+ // We are zooming less than 8x, use 4bit precision
for (int i = 0; i < len; ++i) {
uint tl = buf1[i * 2 + 0];
uint tr = buf1[i * 2 + 1];
uint bl = buf2[i * 2 + 0];
uint br = buf2[i * 2 + 1];
- int distx = ((fracX & 0x0000ffff) + 0x0800) >> 12;
- int disty = ((fracY & 0x0000ffff) + 0x0800) >> 12;
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
b[i] = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
- fracX += fdx;
- fracY += fdy;
+ fx += fdx;
+ fy += fdy;
}
}
@@ -2897,6 +2997,11 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
}
}
} else {
+ // When templated 'fetch' should be inlined at compile time:
+ const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>;
+
+ const QTextureData &image = data->texture;
+
const qreal fdx = data->m11;
const qreal fdy = data->m12;
const qreal fdw = data->m13;
@@ -2927,8 +3032,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
distxs[i] = int((px - x1) * 256);
distys[i] = int((py - y1) * 256);
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -2969,21 +3074,9 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
const QVector<QRgb> *clut = data->texture.colorTable;
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- int image_x1 = data->texture.x1;
- int image_y1 = data->texture.y1;
- int image_x2 = data->texture.x2 - 1;
- int image_y2 = data->texture.y2 - 1;
-
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
if (data->fast_matrix) {
// The increment pr x in the scanline
int fdx = (int)(data->m11 * fixed_scale);
@@ -2995,14 +3088,13 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
fx -= half_point;
fy -= half_point;
+ const BilinearFastTransformFetcher fetcher =
+ (layout->bpp == QPixelLayout::BPP32)
+ ? fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32>
+ : fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPPNone>;
+
if (fdy == 0) { //simple scale, no rotation
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
- FetchPixelFunc fetch = qFetchPixel[layout->bpp];
uint sbuf1[buffer_size];
uint sbuf2[buffer_size];
quint64 buf1[buffer_size];
@@ -3010,84 +3102,19 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
QRgba64 *b = buffer;
while (length) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- int i = 0;
int disty = (fy & 0x0000ffff);
#if defined(__SSE2__)
const __m128i vdy = _mm_set1_epi16(disty);
const __m128i vidy = _mm_set1_epi16(0x10000 - disty);
- if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- if (x1 != x2)
- break;
- sbuf1[i * 2 + 0] = sbuf1[i * 2 + 1] = ((const uint*)s1)[x1];
- sbuf2[i * 2 + 0] = sbuf2[i * 2 + 1] = ((const uint*)s2)[x1];
- fx += fdx;
- }
- int fastLen;
- if (fdx > 0)
- fastLen = qMin(len, int((image_x2 - (fx >> 16)) / data->m11));
- else
- fastLen = qMin(len, int((image_x1 - (fx >> 16)) / data->m11));
- fastLen -= 3;
-
- const __m128i v_fdx = _mm_set1_epi32(fdx*4);
- __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
- for (; i < fastLen; i += 4) {
- int offset = _mm_extract_epi16(v_fx, 1);
- sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
- offset = _mm_extract_epi16(v_fx, 3);
- sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
- offset = _mm_extract_epi16(v_fx, 5);
- sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
- offset = _mm_extract_epi16(v_fx, 7);
- sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
- v_fx = _mm_add_epi32(v_fx, v_fdx);
- }
- fx = _mm_cvtsi128_si32(v_fx);
- }
#endif
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
-
- if (layout->bpp == QPixelLayout::BPP32) {
- sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
- } else {
- sbuf1[i * 2 + 0] = fetch(s1, x1);
- sbuf1[i * 2 + 1] = fetch(s1, x2);
- sbuf2[i * 2 + 0] = fetch(s2, x1);
- sbuf2[i * 2 + 1] = fetch(s2, x2);
- }
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- fx += fdx;
- }
layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
if (disty)
layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff);
+ int distx = (fx & 0x0000ffff);
#if defined(__SSE2__)
const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0));
@@ -3104,13 +3131,12 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
#else
b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
#endif
- fracX += fdx;
+ fx += fdx;
}
length -= len;
b += len;
}
} else { //rotation
- FetchPixelFunc fetch = qFetchPixel[layout->bpp];
uint sbuf1[buffer_size];
uint sbuf2[buffer_size];
quint64 buf1[buffer_size];
@@ -3120,117 +3146,18 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
while (b < end) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- int fracY = fy;
- int i = 0;
-#if defined(__SSE2__)
- if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- if (x1 != x2 && y1 != y2)
- break;
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
- sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
- fx += fdx;
- fy += fdy;
- }
- int fastLen = len;
- if (fdx > 0)
- fastLen = qMin(fastLen, int((qint64(image_x2) * fixed_scale - fx) / fdx));
- else if (fdx < 0)
- fastLen = qMin(fastLen, int((qint64(image_x1) * fixed_scale - fx) / fdx));
- if (fdy > 0)
- fastLen = qMin(fastLen, int((qint64(image_y2) * fixed_scale - fy) / fdy));
- else if (fdy < 0)
- fastLen = qMin(fastLen, int((qint64(image_y1) * fixed_scale - fy) / fdy));
- fastLen -= 3;
-
- const __m128i v_fdx = _mm_set1_epi32(fdx*4);
- const __m128i v_fdy = _mm_set1_epi32(fdy*4);
- __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
- __m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy);
- const int bytesPerLine = data->texture.bytesPerLine;
- const uchar *s1 = data->texture.imageData;
- const uchar *s2 = s1 + bytesPerLine;
- const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
- for (; i < fastLen; i += 4) {
- const __m128i vy = _mm_packs_epi32(_mm_srai_epi32(v_fy, 16), _mm_setzero_si128());
- __m128i voffset = _mm_unpacklo_epi16(_mm_mullo_epi16(vy, vbpl), _mm_mulhi_epu16(vy, vbpl));
- voffset = _mm_add_epi32(voffset, _mm_srli_epi32(v_fx, 16));
-
- int offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
- sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
- offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
- sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
- offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
- sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
- offset = _mm_cvtsi128_si32(voffset);
- sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
-
- v_fx = _mm_add_epi32(v_fx, v_fdx);
- v_fy = _mm_add_epi32(v_fy, v_fdy);
- }
- fx = _mm_cvtsi128_si32(v_fx);
- fy = _mm_cvtsi128_si32(v_fy);
- }
-#endif
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
- if (layout->bpp == QPixelLayout::BPP32) {
- sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
- } else {
- sbuf1[i * 2 + 0] = fetch(s1, x1);
- sbuf1[i * 2 + 1] = fetch(s1, x2);
- sbuf2[i * 2 + 0] = fetch(s2, x1);
- sbuf2[i * 2 + 1] = fetch(s2, x2);
- }
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- fx += fdx;
- fy += fdy;
- }
layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff);
- int disty = (fracY & 0x0000ffff);
+ int distx = (fx & 0x0000ffff);
+ int disty = (fy & 0x0000ffff);
b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
- fracX += fdx;
- fracY += fdy;
+ fx += fdx;
+ fy += fdy;
}
length -= len;
@@ -3238,6 +3165,12 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
}
}
} else {
+ const QTextureData &image = data->texture;
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
@@ -3267,8 +3200,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
distxs[i] = int((px - x1) * (1<<16));
distys[i] = int((py - y1) * (1<<16));
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index db3453898f..49e53973b0 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -43,7 +43,7 @@
/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003 by */
+/* Copyright 2000-2016 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -119,10 +119,6 @@
/* */
/*************************************************************************/
-/* experimental support for gamma correction within the rasterizer */
-#define xxxGRAYS_USE_GAMMA
-
-
/*************************************************************************/
/* */
/* The macro QT_FT_COMPONENT is used in trace mode. It is an implicit */
@@ -133,6 +129,28 @@
#define QT_FT_COMPONENT trace_smooth
+/* Auxiliary macros for token concatenation. */
+#define QT_FT_ERR_XCAT( x, y ) x ## y
+#define QT_FT_ERR_CAT( x, y ) QT_FT_ERR_XCAT( x, y )
+
+#define QT_FT_BEGIN_STMNT do {
+#define QT_FT_END_STMNT } while ( 0 )
+
+#define QT_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+#define QT_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
+
+
+/*
+ * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+ * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
+ * largest error less than 7% compared to the exact value.
+ */
+#define QT_FT_HYPOT( x, y ) \
+ ( x = QT_FT_ABS( x ), \
+ y = QT_FT_ABS( y ), \
+ x > y ? x + ( 3 * y >> 3 ) \
+ : y + ( 3 * x >> 3 ) )
+
#define ErrRaster_MemoryOverflow -4
#if defined(VXWORKS)
@@ -150,6 +168,9 @@
#define qt_ft_longjmp longjmp
#define qt_ft_jmp_buf jmp_buf
+#include <stddef.h>
+typedef ptrdiff_t QT_FT_PtrDist;
+
#define ErrRaster_Invalid_Mode -2
#define ErrRaster_Invalid_Outline -1
#define ErrRaster_Invalid_Argument -3
@@ -171,15 +192,10 @@
/* ANSI compilers (e.g. LCC). */
#define QT_FT_UNUSED( x ) (x) = (x)
- /* Disable the tracing mechanism for simplicity -- developers can */
- /* activate it easily by redefining these two macros. */
-#ifndef QT_FT_ERROR
-#define QT_FT_ERROR( x ) do ; while ( 0 ) /* nothing */
-#endif
-
-#ifndef QT_FT_TRACE
-#define QT_FT_TRACE( x ) do ; while ( 0 ) /* nothing */
-#endif
+#define QT_FT_TRACE5( x ) do { } while ( 0 ) /* nothing */
+#define QT_FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
+#define QT_FT_ERROR( x ) do { } while ( 0 ) /* nothing */
+#define QT_FT_THROW( e ) QT_FT_ERR_CAT( ErrRaster_, e )
#ifndef QT_FT_MEM_SET
#define QT_FT_MEM_SET( d, s, c ) qt_ft_memset( d, s, c )
@@ -189,9 +205,6 @@
#define QT_FT_MEM_ZERO( dest, count ) QT_FT_MEM_SET( dest, 0, count )
#endif
- /* define this to dump debugging information */
-#define xxxDEBUG_GRAYS
-
#define RAS_ARG PWorker worker
#define RAS_ARG_ PWorker worker,
@@ -201,26 +214,47 @@
#define ras (*worker)
-
/* must be at least 6 bits! */
#define PIXEL_BITS 8
#define ONE_PIXEL ( 1L << PIXEL_BITS )
-#define PIXEL_MASK ( -1L << PIXEL_BITS )
#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
-#define SUBPIXELS( x ) ( (TPos)(x) * ( 1 << PIXEL_BITS ) )
+#define SUBPIXELS( x ) ( (TPos)(x) * ONE_PIXEL )
#define FLOOR( x ) ( (x) & -ONE_PIXEL )
#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
#if PIXEL_BITS >= 6
-#define UPSCALE( x ) ( (x) * ( 1 << ( PIXEL_BITS - 6 ) ) )
+#define UPSCALE( x ) ( (x) * ( ONE_PIXEL >> 6 ) )
#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
#else
#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
-#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x ) ( (x) * ( 64 >> PIXEL_BITS ) )
#endif
+/* Compute `dividend / divisor' and return both its quotient and */
+/* remainder, cast to a specific type. This macro also ensures that */
+/* the remainder is always positive. */
+#define QT_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
+QT_FT_BEGIN_STMNT \
+ (quotient) = (type)( (dividend) / (divisor) ); \
+ (remainder) = (type)( (dividend) % (divisor) ); \
+ if ( (remainder) < 0 ) \
+ { \
+ (quotient)--; \
+ (remainder) += (type)(divisor); \
+ } \
+QT_FT_END_STMNT
+
+ /* These macros speed up repetitive divisions by replacing them */
+ /* with multiplications and right shifts. */
+#define QT_FT_UDIVPREP( b ) \
+ long b ## _r = (long)( ULONG_MAX >> PIXEL_BITS ) / ( b )
+#define QT_FT_UDIV( a, b ) \
+ ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
+ ( sizeof( long ) * CHAR_BIT - PIXEL_BITS ) )
+
+
/*************************************************************************/
/* */
/* TYPE DEFINITIONS */
@@ -230,28 +264,9 @@
/* need to define them to "float" or "double" when experimenting with */
/* new algorithms */
- typedef int TCoord; /* integer scanline/pixel coordinate */
- typedef int TPos; /* sub-pixel coordinate */
-
- /* determine the type used to store cell areas. This normally takes at */
- /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */
- /* `long' instead of `int', otherwise bad things happen */
-
-#if PIXEL_BITS <= 7
-
- typedef int TArea;
-
-#else /* PIXEL_BITS >= 8 */
-
- /* approximately determine the size of integers using an ANSI-C header */
-#if QT_FT_UINT_MAX == 0xFFFFU
- typedef long TArea;
-#else
- typedef int TArea;
-#endif
-
-#endif /* PIXEL_BITS >= 8 */
-
+ typedef long TCoord; /* integer scanline/pixel coordinate */
+ typedef long TPos; /* sub-pixel coordinate */
+ typedef long TArea ; /* cell areas, coordinate products */
/* maximal number of gray spans in a call to the span callback */
#define QT_FT_MAX_GRAY_SPANS 256
@@ -281,17 +296,11 @@
int invalid;
PCell cells;
- int max_cells;
- int num_cells;
+ QT_FT_PtrDist max_cells;
+ QT_FT_PtrDist num_cells;
- TCoord cx, cy;
TPos x, y;
- TPos last_ey;
-
- QT_FT_Vector bez_stack[32 * 3 + 1];
- int lev_stack[32];
-
QT_FT_Outline outline;
QT_FT_Bitmap target;
QT_FT_BBox clip_box;
@@ -304,8 +313,6 @@
int band_size;
int band_shoot;
- int conic_level;
- int cubic_level;
qt_ft_jmp_buf jump_buffer;
@@ -313,7 +320,7 @@
long buffer_size;
PCell* ycells;
- int ycount;
+ TPos ycount;
int skip_spans;
} TWorker, *PWorker;
@@ -343,7 +350,7 @@
/* */
static void
gray_init_cells( RAS_ARG_ void* buffer,
- long byte_size )
+ long byte_size )
{
ras.buffer = buffer;
ras.buffer_size = byte_size;
@@ -406,31 +413,25 @@
/* */
/* Record the current cell in the table. */
/* */
- static void
- gray_record_cell( RAS_ARG )
+ static PCell
+ gray_find_cell( RAS_ARG )
{
PCell *pcell, cell;
- int x = ras.ex;
+ TPos x = ras.ex;
- if ( ras.invalid || !( ras.area | ras.cover ) )
- return;
- if ( x > ras.max_ex )
- x = ras.max_ex;
+ if ( x > ras.count_ex )
+ x = ras.count_ex;
pcell = &ras.ycells[ras.ey];
-
for (;;)
{
cell = *pcell;
if ( cell == NULL || cell->x > x )
break;
- if ( cell->x == x ) {
- cell->area += ras.area;
- cell->cover += ras.cover;
- return;
- }
+ if ( cell->x == x )
+ goto Exit;
pcell = &cell->next;
}
@@ -440,11 +441,28 @@
cell = ras.cells + ras.num_cells++;
cell->x = x;
- cell->area = ras.area;
- cell->cover = ras.cover;
+ cell->area = 0;
+ cell->cover = 0;
cell->next = *pcell;
*pcell = cell;
+
+ Exit:
+ return cell;
+ }
+
+
+ static void
+ gray_record_cell( RAS_ARG )
+ {
+ if ( ras.area | ras.cover )
+ {
+ PCell cell = gray_find_cell( RAS_VAR );
+
+
+ cell->area += ras.area;
+ cell->cover += ras.cover;
+ }
}
@@ -490,8 +508,8 @@
ras.ey = ey;
}
- ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
- ex >= ras.count_ex );
+ ras.invalid = ( (unsigned int)ey >= (unsigned int)ras.count_ey ||
+ ex >= ras.count_ex );
}
@@ -513,12 +531,13 @@
ras.cover = 0;
ras.ex = ex - ras.min_ex;
ras.ey = ey - ras.min_ey;
- ras.last_ey = SUBPIXELS( ey );
ras.invalid = 0;
gray_set_cell( RAS_VAR_ ex, ey );
}
+// The new render-line implementation is not yet used
+#if 1
/*************************************************************************/
/* */
@@ -531,9 +550,9 @@
TPos x2,
TCoord y2 )
{
- TCoord ex1, ex2, fx1, fx2, delta;
+ TCoord ex1, ex2, fx1, fx2, delta, mod;
int p, first, dx;
- int incr, lift, mod, rem;
+ int incr;
dx = x2 - x1;
@@ -575,13 +594,7 @@
dx = -dx;
}
- delta = (TCoord)( p / dx );
- mod = (TCoord)( p % dx );
- if ( mod < 0 )
- {
- delta--;
- mod += (TCoord)dx;
- }
+ QT_FT_DIV_MOD( TCoord, p, dx, delta, mod );
ras.area += (TArea)( fx1 + first ) * delta;
ras.cover += delta;
@@ -592,14 +605,11 @@
if ( ex1 != ex2 )
{
- p = ONE_PIXEL * ( y2 - y1 + delta );
- lift = (TCoord)( p / dx );
- rem = (TCoord)( p % dx );
- if ( rem < 0 )
- {
- lift--;
- rem += (TCoord)dx;
- }
+ TCoord lift, rem;
+
+
+ p = ONE_PIXEL * ( y2 - y1 + delta );
+ QT_FT_DIV_MOD( TCoord, p, dx, lift, rem );
mod -= (int)dx;
@@ -635,38 +645,24 @@
gray_render_line( RAS_ARG_ TPos to_x,
TPos to_y )
{
- TCoord ey1, ey2, fy1, fy2;
+ TCoord ey1, ey2, fy1, fy2, mod;
TPos dx, dy, x, x2;
int p, first;
- int delta, rem, mod, lift, incr;
+ int delta, rem, lift, incr;
- ey1 = TRUNC( ras.last_ey );
+ ey1 = TRUNC( ras.y );
ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
- fy1 = (TCoord)( ras.y - ras.last_ey );
+ fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
dx = to_x - ras.x;
dy = to_y - ras.y;
- /* XXX: we should do something about the trivial case where dx == 0, */
- /* as it happens very often! */
-
/* perform vertical clipping */
- {
- TCoord min, max;
-
-
- min = ey1;
- max = ey2;
- if ( ey1 > ey2 )
- {
- min = ey2;
- max = ey1;
- }
- if ( min >= ras.max_ey || max < ras.min_ey )
- goto End;
- }
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
/* everything is on a single scanline */
if ( ey1 == ey2 )
@@ -773,13 +769,7 @@
if ( ey1 != ey2 )
{
p = ONE_PIXEL * dx;
- lift = (int)( p / dy );
- rem = (int)( p % dy );
- if ( rem < 0 )
- {
- lift--;
- rem += (int)dy;
- }
+ QT_FT_DIV_MOD( int, p, dy, lift, rem );
mod -= (int)dy;
while ( ey1 != ey2 )
@@ -810,10 +800,147 @@
End:
ras.x = to_x;
ras.y = to_y;
- ras.last_ey = SUBPIXELS( ey2 );
}
+#else
+
+ /*************************************************************************/
+ /* */
+ /* Render a straight line across multiple cells in any direction. */
+ /* */
+ static void
+ gray_render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TPos dx, dy, fx1, fy1, fx2, fy2;
+ TCoord ex1, ex2, ey1, ey2;
+
+
+ ex1 = TRUNC( ras.x );
+ ex2 = TRUNC( to_x );
+ ey1 = TRUNC( ras.y );
+ ey2 = TRUNC( to_y );
+
+ /* perform vertical clipping */
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ fx1 = ras.x - SUBPIXELS( ex1 );
+ fy1 = ras.y - SUBPIXELS( ey1 );
+
+ if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
+ ;
+ else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
+ {
+ ex1 = ex2;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ }
+ else if ( dx == 0 )
+ {
+ if ( dy > 0 ) /* vertical line up */
+ do
+ {
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = 0;
+ ey1++;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ else /* vertical line down */
+ do
+ {
+ fy2 = 0;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ }
+ else /* any other line */
+ {
+ TArea prod = dx * fy1 - dy * fx1;
+ QT_FT_UDIVPREP( dx );
+ QT_FT_UDIVPREP( dy );
+
+
+ /* The fundamental value `prod' determines which side and the */
+ /* exact coordinate where the line exits current cell. It is */
+ /* also easily updated when moving from one cell to the next. */
+ do
+ {
+ if ( prod <= 0 &&
+ prod - dx * ONE_PIXEL > 0 ) /* left */
+ {
+ fx2 = 0;
+ fy2 = (TPos)QT_FT_UDIV( -prod, -dx );
+ prod -= dy * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = ONE_PIXEL;
+ fy1 = fy2;
+ ex1--;
+ }
+ else if ( prod - dx * ONE_PIXEL <= 0 &&
+ prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
+ {
+ prod -= dx * ONE_PIXEL;
+ fx2 = (TPos)QT_FT_UDIV( -prod, dy );
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = 0;
+ ey1++;
+ }
+ else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
+ prod + dy * ONE_PIXEL >= 0 ) /* right */
+ {
+ prod += dy * ONE_PIXEL;
+ fx2 = ONE_PIXEL;
+ fy2 = (TPos)QT_FT_UDIV( prod, dx );
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = 0;
+ fy1 = fy2;
+ ex1++;
+ }
+ else /* ( prod + dy * ONE_PIXEL < 0 &&
+ prod > 0 ) down */
+ {
+ fx2 = (TPos)QT_FT_UDIV( prod, -dy );
+ fy2 = 0;
+ prod += dx * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ }
+
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ex1 != ex2 || ey1 != ey2 );
+ }
+
+ fx2 = to_x - SUBPIXELS( ex2 );
+ fy2 = to_y - SUBPIXELS( ey2 );
+
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ }
+
+#endif
+
static void
gray_split_conic( QT_FT_Vector* base )
{
@@ -838,52 +965,11 @@
gray_render_conic( RAS_ARG_ const QT_FT_Vector* control,
const QT_FT_Vector* to )
{
+ QT_FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */
+ QT_FT_Vector* arc = bez_stack;
TPos dx, dy;
- int top, level;
- int* levels;
- QT_FT_Vector* arc;
-
-
- dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
-
- level = 1;
- dx = dx / ras.conic_level;
- while ( dx > 0 )
- {
- dx >>= 2;
- level++;
- }
+ int draw, split;
- /* a shortcut to speed things up */
- if ( level <= 1 )
- {
- /* we compute the mid-point directly in order to avoid */
- /* calling gray_split_conic() */
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
- mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- return;
- }
-
- arc = ras.bez_stack;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
arc[0].x = UPSCALE( to->x );
arc[0].y = UPSCALE( to->y );
@@ -892,54 +978,51 @@
arc[2].x = ras.x;
arc[2].y = ras.y;
- while ( top >= 0 )
+ /* short-cut the arc that crosses the current band */
+ if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+ TRUNC( arc[1].y ) >= ras.max_ey &&
+ TRUNC( arc[2].y ) >= ras.max_ey ) ||
+ ( TRUNC( arc[0].y ) < ras.min_ey &&
+ TRUNC( arc[1].y ) < ras.min_ey &&
+ TRUNC( arc[2].y ) < ras.min_ey ) )
{
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
-
-
- min = max = arc[0].y;
-
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
+ ras.x = arc[0].x;
+ ras.y = arc[0].y;
+ return;
+ }
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
+ dx = QT_FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
+ dy = QT_FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
+ if ( dx < dy )
+ dx = dy;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
- goto Draw;
+ /* We can calculate the number of necessary bisections because */
+ /* each bisection predictably reduces deviation exactly 4-fold. */
+ /* Even 32-bit deviation would vanish after 16 bisections. */
+ draw = 1;
+ while ( dx > ONE_PIXEL / 4 )
+ {
+ dx >>= 2;
+ draw <<= 1;
+ }
+ /* We use decrement counter to count the total number of segments */
+ /* to draw starting from 2^level. Before each draw we split as */
+ /* many times as there are trailing zeros in the counter. */
+ do
+ {
+ split = 1;
+ while ( ( draw & split ) == 0 )
+ {
gray_split_conic( arc );
arc += 2;
- top++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
+ split <<= 1;
}
- Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
- mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- top--;
- arc -= 2;
- }
- }
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+ arc -= 2;
- return;
+ } while ( --draw );
}
@@ -976,60 +1059,13 @@
const QT_FT_Vector* control2,
const QT_FT_Vector* to )
{
- TPos dx, dy, da, db;
- int top, level;
- int* levels;
- QT_FT_Vector* arc;
+ QT_FT_Vector bez_stack[16 * 3 + 1]; /* enough to accommodate bisections */
+ QT_FT_Vector* arc = bez_stack;
+ TPos dx, dy, dx_, dy_;
+ TPos dx1, dy1, dx2, dy2;
+ TPos L, s, s_limit;
- dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
- da = dx;
-
- dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->y + control2->y );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
- db = dx;
-
- level = 1;
- da = da / ras.cubic_level;
- db = db / ras.conic_level;
- while ( da > 0 || db > 0 )
- {
- da >>= 2;
- db >>= 3;
- level++;
- }
-
- if ( level <= 1 )
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x +
- 3 * UPSCALE( control1->x + control2->x ) ) / 8;
- mid_y = ( ras.y + to_y +
- 3 * UPSCALE( control1->y + control2->y ) ) / 8;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
- return;
- }
-
- arc = ras.bez_stack;
arc[0].x = UPSCALE( to->x );
arc[0].y = UPSCALE( to->y );
arc[1].x = UPSCALE( control2->x );
@@ -1039,56 +1075,77 @@
arc[3].x = ras.x;
arc[3].y = ras.y;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
+ /* short-cut the arc that crosses the current band */
+ if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+ TRUNC( arc[1].y ) >= ras.max_ey &&
+ TRUNC( arc[2].y ) >= ras.max_ey &&
+ TRUNC( arc[3].y ) >= ras.max_ey ) ||
+ ( TRUNC( arc[0].y ) < ras.min_ey &&
+ TRUNC( arc[1].y ) < ras.min_ey &&
+ TRUNC( arc[2].y ) < ras.min_ey &&
+ TRUNC( arc[3].y ) < ras.min_ey ) )
+ {
+ ras.x = arc[0].x;
+ ras.y = arc[0].y;
+ return;
+ }
- while ( top >= 0 )
+ for (;;)
{
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
-
-
- min = max = arc[0].y;
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[3].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
- goto Draw;
- gray_split_cubic( arc );
- arc += 3;
- top ++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
- }
+ /* Decide whether to split or draw. See `Rapid Termination */
+ /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
+ /* F. Hain, at */
+ /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
- Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
+ /* dx and dy are x and y components of the P0-P3 chord vector. */
+ dx = dx_ = arc[3].x - arc[0].x;
+ dy = dy_ = arc[3].y - arc[0].y;
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
- mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+ L = QT_FT_HYPOT( dx_, dy_ );
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
- top --;
- arc -= 3;
- }
- }
+ /* Avoid possible arithmetic overflow below by splitting. */
+ if ( L > 32767 )
+ goto Split;
+
+ /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+ s_limit = L * (TPos)( ONE_PIXEL / 6 );
+
+ /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+ dx1 = arc[1].x - arc[0].x;
+ dy1 = arc[1].y - arc[0].y;
+ s = QT_FT_ABS( dy * dx1 - dx * dy1 );
+
+ if ( s > s_limit )
+ goto Split;
+
+ /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+ dx2 = arc[2].x - arc[0].x;
+ dy2 = arc[2].y - arc[0].y;
+ s = QT_FT_ABS( dy * dx2 - dx * dy2 );
+
+ if ( s > s_limit )
+ goto Split;
+
+ /* Split super curvy segments where the off points are so far
+ from the chord that the angles P0-P1-P3 or P0-P2-P3 become
+ acute as detected by appropriate dot products. */
+ if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
+ dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
+ goto Split;
- return;
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+
+ if ( arc == bez_stack )
+ return;
+
+ arc -= 3;
+ continue;
+
+ Split:
+ gray_split_cubic( arc );
+ arc += 3;
+ }
}
@@ -1101,7 +1158,8 @@
/* record current cell, if any */
- gray_record_cell( worker );
+ if ( !ras.invalid )
+ gray_record_cell( worker );
/* start to a new position */
x = UPSCALE( to->x );
@@ -1109,15 +1167,15 @@
gray_start_cell( worker, TRUNC( x ), TRUNC( y ) );
- worker->x = x;
- worker->y = y;
+ ras.x = x;
+ ras.y = y;
return 0;
}
static void
- gray_render_span( int count,
+ gray_render_span( int count,
const QT_FT_Span* spans,
- PWorker worker )
+ PWorker worker )
{
unsigned char* p;
QT_FT_Bitmap* map = &worker->target;
@@ -1129,34 +1187,30 @@
/* first of all, compute the scanline offset */
p = (unsigned char*)map->buffer - spans->y * map->pitch;
if ( map->pitch >= 0 )
- p += ( map->rows - 1 ) * map->pitch;
+ p += ( map->rows - 1 ) * (unsigned int)map->pitch;
if ( coverage )
{
+ unsigned char* q = p + spans->x;
+
+
/* For small-spans it is faster to do it by ourselves than
* calling `memset'. This is mainly due to the cost of the
* function call.
*/
- if ( spans->len >= 8 )
- QT_FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
- else
+ switch ( spans->len )
{
- unsigned char* q = p + spans->x;
-
-
- switch ( spans->len )
- {
- case 7: *q++ = (unsigned char)coverage;
- case 6: *q++ = (unsigned char)coverage;
- case 5: *q++ = (unsigned char)coverage;
- case 4: *q++ = (unsigned char)coverage;
- case 3: *q++ = (unsigned char)coverage;
- case 2: *q++ = (unsigned char)coverage;
- case 1: *q = (unsigned char)coverage;
- default:
- ;
- }
+ case 7: *q++ = coverage;
+ case 6: *q++ = coverage;
+ case 5: *q++ = coverage;
+ case 4: *q++ = coverage;
+ case 3: *q++ = coverage;
+ case 2: *q++ = coverage;
+ case 1: *q = coverage;
+ case 0: break;
+ default:
+ QT_FT_MEM_SET( q, coverage, spans->len );
}
}
}
@@ -1169,9 +1223,7 @@
TPos area,
int acount )
{
- QT_FT_Span* span;
- int coverage;
- int skip;
+ int coverage;
/* compute the coverage line's coverage, depending on the */
@@ -1204,14 +1256,24 @@
x += (TCoord)ras.min_ex;
/* QT_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
- if ( x >= 32768 )
+ if ( x >= 32767 )
x = 32767;
+ /* QT_FT_Span.y is a 16-bit short, so limit our coordinates appropriately */
+ if ( y >= 32767 )
+ y = 32767;
+
if ( coverage )
{
+ QT_FT_Span* span;
+ int count;
+ int skip;
+
+
/* see whether we can add this span to the current list */
- span = ras.gray_spans + ras.num_gray_spans - 1;
- if ( ras.num_gray_spans > 0 &&
+ count = ras.num_gray_spans;
+ span = ras.gray_spans + count - 1;
+ if ( count > 0 &&
span->y == y &&
(int)span->x + span->len == (int)x &&
span->coverage == coverage )
@@ -1220,9 +1282,9 @@
return;
}
- if ( ras.num_gray_spans >= QT_FT_MAX_GRAY_SPANS )
+ if ( count >= QT_FT_MAX_GRAY_SPANS )
{
- if ( ras.render_span && ras.num_gray_spans > ras.skip_spans )
+ if ( ras.render_span && count > ras.skip_spans )
{
skip = ras.skip_spans > 0 ? ras.skip_spans : 0;
ras.render_span( ras.num_gray_spans - skip,
@@ -1304,6 +1366,8 @@
if ( ras.num_cells == 0 )
return;
+ QT_FT_TRACE7(( "gray_sweep: start\n" ));
+
for ( yindex = 0; yindex < ras.ycount; yindex++ )
{
PCell cell = ras.ycells[yindex];
@@ -1333,6 +1397,8 @@
gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
ras.count_ex - x );
}
+
+ QT_FT_TRACE7(( "gray_sweep: end\n" ));
}
/*************************************************************************/
@@ -1366,7 +1432,7 @@
/* */
static
int QT_FT_Outline_Decompose( const QT_FT_Outline* outline,
- void* user )
+ void* user )
{
#undef SCALED
#define SCALED( x ) (x)
@@ -1384,6 +1450,9 @@
int error;
char tag; /* current point's state */
+ if ( !outline )
+ return ErrRaster_Invalid_Outline;
+
first = 0;
for ( n = 0; n < outline->n_contours; n++ )
@@ -1392,16 +1461,17 @@
last = outline->contours[n];
+ if ( last < 0 )
+ goto Invalid_Outline;
limit = outline->points + last;
- v_start = outline->points[first];
- v_last = outline->points[last];
-
+ v_start = outline->points[first];
v_start.x = SCALED( v_start.x );
v_start.y = SCALED( v_start.y );
- v_last.x = SCALED( v_last.x );
- v_last.y = SCALED( v_last.y );
+ v_last = outline->points[last];
+ v_last.x = SCALED( v_last.x );
+ v_last.y = SCALED( v_last.y );
v_control = v_start;
@@ -1437,6 +1507,8 @@
tags--;
}
+ QT_FT_TRACE5(( " move to (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0 ));
error = gray_move_to( &v_start, user );
if ( error )
goto Exit;
@@ -1457,6 +1529,8 @@
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
+ QT_FT_TRACE5(( " line to (%.2f, %.2f)\n",
+ vec.x / 64.0, vec.y / 64.0 ));
gray_render_line(user, UPSCALE(vec.x), UPSCALE(vec.y));
continue;
}
@@ -1482,6 +1556,10 @@
if ( tag == QT_FT_CURVE_TAG_ON )
{
+ QT_FT_TRACE5(( " conic to (%.2f, %.2f)"
+ " with control (%.2f, %.2f)\n",
+ vec.x / 64.0, vec.y / 64.0,
+ v_control.x / 64.0, v_control.y / 64.0 ));
gray_render_conic(user, &v_control, &vec);
continue;
}
@@ -1492,11 +1570,20 @@
v_middle.x = ( v_control.x + vec.x ) / 2;
v_middle.y = ( v_control.y + vec.y ) / 2;
+ QT_FT_TRACE5(( " conic to (%.2f, %.2f)"
+ " with control (%.2f, %.2f)\n",
+ v_middle.x / 64.0, v_middle.y / 64.0,
+ v_control.x / 64.0, v_control.y / 64.0 ));
gray_render_conic(user, &v_control, &v_middle);
+
v_control = vec;
goto Do_Conic;
}
+ QT_FT_TRACE5(( " conic to (%.2f, %.2f)"
+ " with control (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0,
+ v_control.x / 64.0, v_control.y / 64.0 ));
gray_render_conic(user, &v_control, &v_start);
goto Close;
}
@@ -1527,10 +1614,20 @@
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
+ QT_FT_TRACE5(( " cubic to (%.2f, %.2f)"
+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
+ vec.x / 64.0, vec.y / 64.0,
+ vec1.x / 64.0, vec1.y / 64.0,
+ vec2.x / 64.0, vec2.y / 64.0 ));
gray_render_cubic(user, &vec1, &vec2, &vec);
continue;
}
+ QT_FT_TRACE5(( " cubic to (%.2f, %.2f)"
+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0,
+ vec1.x / 64.0, vec1.y / 64.0,
+ vec2.x / 64.0, vec2.y / 64.0 ));
gray_render_cubic(user, &vec1, &vec2, &v_start);
goto Close;
}
@@ -1538,15 +1635,19 @@
}
/* close the contour with a line segment */
+ QT_FT_TRACE5(( " line to (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0 ));
gray_render_line(user, UPSCALE(v_start.x), UPSCALE(v_start.y));
Close:
first = last + 1;
}
+ QT_FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
return 0;
Exit:
+ QT_FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
return error;
Invalid_Outline:
@@ -1559,7 +1660,6 @@
} TBand;
-
static int
gray_convert_glyph_inner( RAS_ARG )
{
@@ -1568,7 +1668,8 @@
if ( qt_ft_setjmp( ras.jump_buffer ) == 0 )
{
error = QT_FT_Outline_Decompose( &ras.outline, &ras );
- gray_record_cell( RAS_VAR );
+ if ( !ras.invalid )
+ gray_record_cell( RAS_VAR );
}
else
{
@@ -1610,29 +1711,12 @@
ras.count_ex = ras.max_ex - ras.min_ex;
ras.count_ey = ras.max_ey - ras.min_ey;
- /* simple heuristic used to speed-up the bezier decomposition -- see */
- /* the code in gray_render_conic() and gray_render_cubic() for more */
- /* details */
- ras.conic_level = 32;
- ras.cubic_level = 16;
-
- {
- int level = 0;
-
-
- if ( ras.count_ex > 24 || ras.count_ey > 24 )
- level++;
- if ( ras.count_ex > 120 || ras.count_ey > 120 )
- level++;
-
- ras.conic_level <<= level;
- ras.cubic_level <<= level;
- }
-
- /* setup vertical bands */
+ /* set up vertical bands */
num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
- if ( num_bands == 0 ) num_bands = 1;
- if ( num_bands >= 39 ) num_bands = 39;
+ if ( num_bands == 0 )
+ num_bands = 1;
+ if ( num_bands >= 39 )
+ num_bands = 39;
ras.band_shoot = 0;
@@ -1766,11 +1850,14 @@
if (raster->buffer_allocated_size < MINIMUM_POOL_SIZE )
return ErrRaster_OutOfMemory;
+ if ( !outline )
+ return ErrRaster_Invalid_Outline;
+
/* return immediately if the outline is empty */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
return 0;
- if ( !outline || !outline->contours || !outline->points )
+ if ( !outline->contours || !outline->points )
return ErrRaster_Invalid_Outline;
if ( outline->n_points !=
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index ddea168e72..5fc5d5364e 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -929,11 +929,11 @@ QPoint QPaintEngine::coordinateOffset() const
void QPaintEngine::setSystemClip(const QRegion &region)
{
Q_D(QPaintEngine);
- d->systemClip = region;
+ d->baseSystemClip = region;
// Be backward compatible and only call d->systemStateChanged()
// if we currently have a system transform/viewport set.
+ d->updateSystemClip();
if (d->hasSystemTransform || d->hasSystemViewport) {
- d->transformSystemClip();
d->systemStateChanged();
}
}
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index 9d511f9bad..8ac3fcff5c 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -71,6 +71,7 @@ public:
QPaintDevice *pdev;
QPaintEngine *q_ptr;
+ QRegion baseSystemClip;
QRegion systemClip;
QRect systemRect;
QRegion systemViewport;
@@ -79,8 +80,9 @@ public:
uint hasSystemTransform : 1;
uint hasSystemViewport : 1;
- inline void transformSystemClip()
+ inline void updateSystemClip()
{
+ systemClip = baseSystemClip;
if (systemClip.isEmpty())
return;
@@ -104,15 +106,30 @@ public:
inline void setSystemTransform(const QTransform &xform)
{
systemTransform = xform;
- if ((hasSystemTransform = !xform.isIdentity()) || hasSystemViewport)
- transformSystemClip();
- systemStateChanged();
+ hasSystemTransform = !xform.isIdentity();
+ updateSystemClip();
+ if (q_ptr->state)
+ systemStateChanged();
}
inline void setSystemViewport(const QRegion &region)
{
systemViewport = region;
hasSystemViewport = !systemViewport.isEmpty();
+ updateSystemClip();
+ if (q_ptr->state)
+ systemStateChanged();
+ }
+
+ inline void setSystemTransformAndViewport(const QTransform &xform, const QRegion &region)
+ {
+ systemTransform = xform;
+ hasSystemTransform = !xform.isIdentity();
+ systemViewport = region;
+ hasSystemViewport = !systemViewport.isEmpty();
+ updateSystemClip();
+ if (q_ptr->state)
+ systemStateChanged();
}
virtual void systemStateChanged() { }
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 7b8bae1642..bac9740892 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1465,6 +1465,7 @@ void QPdfEnginePrivate::writeHeader()
addXrefEntry(0,false);
xprintf("%%PDF-1.4\n");
+ xprintf("%%\303\242\303\243\n");
writeInfo();
@@ -1597,7 +1598,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
"/CapHeight " << properties.capHeight.toReal()*scale << "\n"
"/StemV " << properties.lineWidth.toReal()*scale << "\n"
"/FontFile2 " << fontstream << "0 R\n"
- ">> endobj\n";
+ ">>\nendobj\n";
write(descriptor);
}
{
@@ -1615,7 +1616,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
"stream\n";
write(header);
int len = writeCompressed(fontData);
- write("endstream\n"
+ write("\nendstream\n"
"endobj\n");
addXrefEntry(length_object);
xprintf("%d\n"
@@ -1642,7 +1643,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
xprintf("<< /Length %d >>\n"
"stream\n", touc.length());
write(touc);
- write("endstream\n"
+ write("\nendstream\n"
"endobj\n");
}
{
@@ -1748,7 +1749,7 @@ void QPdfEnginePrivate::writePage()
xprintf("stream\n");
QIODevice *content = currentPage->stream();
int len = writeCompressed(content);
- xprintf("endstream\n"
+ xprintf("\nendstream\n"
"endobj\n");
addXrefEntry(pageStreamLength);
@@ -1794,7 +1795,13 @@ int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
return object;
}
-void QPdfEnginePrivate::printString(const QString &string) {
+void QPdfEnginePrivate::printString(const QString &string)
+{
+ if (string.isEmpty()) {
+ write("()");
+ return;
+ }
+
// The 'text string' type in PDF is encoded either as PDFDocEncoding, or
// Unicode UTF-16 with a Unicode byte order mark as the first character
// (0xfeff), with the high-order byte first.
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index b8bbdefa37..e006fad437 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -70,6 +70,13 @@
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
#endif
+#ifndef GL_FRAMEBUFFER_SRB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE
+#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA
+#endif
+
QT_BEGIN_NAMESPACE
class QPlatformBackingStorePrivate
@@ -269,7 +276,7 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
}
static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
- QOpenGLTextureBlitter *blitter, const QPoint &offset)
+ QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb)
{
const QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty())
@@ -289,7 +296,15 @@ static void blitTextureForWidget(const QPlatformTextureList *textures, int idx,
deviceRect(rectInWindow, window).size(),
QOpenGLTextureBlitter::OriginBottomLeft);
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb);
+ if (srgb && canUseSrgb)
+ funcs->glEnable(GL_FRAMEBUFFER_SRGB);
+
blitter->blit(textures->textureId(idx), target, source);
+
+ if (srgb && canUseSrgb)
+ funcs->glDisable(GL_FRAMEBUFFER_SRGB);
}
/*!
@@ -334,10 +349,23 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window);
+ bool canUseSrgb = false;
+ // If there are any sRGB textures in the list, check if the destination
+ // framebuffer is sRGB capable.
+ for (int i = 0; i < textures->count(); ++i) {
+ if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) {
+ GLint cap = 0;
+ funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap);
+ if (cap)
+ canUseSrgb = true;
+ break;
+ }
+ }
+
// Textures for renderToTexture widgets.
for (int i = 0; i < textures->count(); ++i) {
if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
- blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset);
+ blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb);
}
// Backingstore texture with the normal widgets.
@@ -406,7 +434,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
- blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset);
+ blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb);
}
funcs->glDisable(GL_BLEND);
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index ec56aaa002..d1ce67a65d 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -78,7 +78,8 @@ class Q_GUI_EXPORT QPlatformTextureList : public QObject
Q_DECLARE_PRIVATE(QPlatformTextureList)
public:
enum Flag {
- StacksOnTop = 0x01
+ StacksOnTop = 0x01,
+ TextureIsSrgb = 0x02
};
Q_DECLARE_FLAGS(Flags, Flag)
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index 064c2aca7f..746200fd9c 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -436,7 +436,7 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert
const quint32 *indices, int indexCount, qint32 value)
{
Q_ASSERT(indexCount != 0);
- typedef QVarLengthArray<quint8, 16> ScanLine;
+ typedef QVarLengthArray<quint16, 16> ScanLine;
QVarLengthArray<ScanLine, 128> scans(height);
int first = 0;
for (int i = 1; i < indexCount; ++i) {
@@ -461,16 +461,16 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert
for (int y = fromY; y < toY; ++y) {
quint32 c = quint32(x >> 8);
if (c < quint32(width))
- scans[y].append(quint8(c));
+ scans[y].append(quint16(c));
x += dx;
}
}
for (int i = 0; i < height; ++i) {
- quint8 *scanline = scans[i].data();
+ quint16 *scanline = scans[i].data();
int size = scans[i].size();
for (int j = 1; j < size; ++j) {
int k = j;
- quint8 value = scanline[k];
+ quint16 value = scanline[k];
for (; k != 0 && value < scanline[k - 1]; --k)
scanline[k] = scanline[k - 1];
scanline[k] = value;
@@ -478,7 +478,7 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert
qint32 *line = bits + i * width;
int j = 0;
for (; j + 1 < size; j += 2) {
- for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x)
+ for (quint16 x = scanline[j]; x < scanline[j + 1]; ++x)
line[x] = value;
}
if (j < size) {
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 92eeaf7919..f5fc562e13 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -136,7 +136,7 @@ QByteArray QFontSubset::widthArray() const
QByteArray width;
QPdf::ByteStream s(&width);
- QFixed scale = QFixed(1000)/emSquare;
+ const qreal scale = 1000.0/emSquare.toInt();
QFixed defWidth = widths[0];
//qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal());
@@ -145,7 +145,7 @@ QByteArray QFontSubset::widthArray() const
defWidth = 0;
}
if (defWidth > 0) {
- s << "/DW " << (defWidth*scale).toInt();
+ s << "/DW " << qRound(defWidth.toInt() * scale);
} else {
s << "/W [";
for (int g = 0; g < nGlyphs();) {
@@ -174,11 +174,11 @@ QByteArray QFontSubset::widthArray() const
if (endnonlinear > start) {
s << start << '[';
for (int i = start; i < endnonlinear; ++i)
- s << (widths[i]*scale).toInt();
+ s << qRound(widths[i].toInt() * scale);
s << "]\n";
}
if (startLinear)
- s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
+ s << startLinear << g - 1 << qRound(widths[startLinear].toInt() * scale) << '\n';
}
s << "]\n";
}
diff --git a/src/gui/vulkan/KHRONOS_LICENSE.txt b/src/gui/vulkan/KHRONOS_LICENSE.txt
new file mode 100644
index 0000000000..7f6672d50e
--- /dev/null
+++ b/src/gui/vulkan/KHRONOS_LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2015-2017 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are 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 Materials.
+
+THE MATERIALS ARE 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
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp
new file mode 100644
index 0000000000..6201d3ec11
--- /dev/null
+++ b/src/gui/vulkan/qplatformvulkaninstance.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** 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 "qplatformvulkaninstance.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPlatformVulkanInstance
+ \since 5.10
+ \internal
+ \preliminary
+ \ingroup qpa
+
+ \brief The QPlatformVulkanInstance class provides an abstraction for Vulkan instances.
+
+ The platform Vulkan instance is responsible for loading a Vulkan library,
+ resolving the basic entry points for creating instances, providing support
+ for creating new or adopting existing VkInstances, and abstracting some
+ WSI-specifics like checking if a given queue family can be used to present
+ using a given window.
+
+ \note platform plugins will typically subclass not this class, but rather
+ QBasicVulkanPlatformInstance.
+
+ \note Vulkan instance creation is split into two phases: a new
+ QPlatformVulkanInstance is expected to load the Vulkan library and do basic
+ initialization, after which the supported layers and extensions can be
+ queried. Everything else is deferred into createOrAdoptInstance().
+*/
+
+class QPlatformVulkanInstancePrivate
+{
+public:
+ QPlatformVulkanInstancePrivate() { }
+};
+
+QPlatformVulkanInstance::QPlatformVulkanInstance()
+ : d_ptr(new QPlatformVulkanInstancePrivate)
+{
+}
+
+QPlatformVulkanInstance::~QPlatformVulkanInstance()
+{
+}
+
+void QPlatformVulkanInstance::presentQueued(QWindow *window)
+{
+ Q_UNUSED(window);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qpodlist_p.h b/src/gui/vulkan/qplatformvulkaninstance.h
index 95990e0bb6..5513d1767d 100644
--- a/src/corelib/tools/qpodlist_p.h
+++ b/src/gui/vulkan/qplatformvulkaninstance.h
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the QtCore module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,73 +37,55 @@
**
****************************************************************************/
-#ifndef QPODLIST_P_H
-#define QPODLIST_P_H
+#ifndef QPLATFORMVULKANINSTANCE_H
+#define QPLATFORMVULKANINSTANCE_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.
+// 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 <QtCore/private/qglobal_p.h>
-#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(vulkan)
+
+#include <qvulkaninstance.h>
QT_BEGIN_NAMESPACE
+class QPlatformVulkanInstancePrivate;
-template <typename T, int Prealloc>
-class QPodList : public QVarLengthArray<T, Prealloc>
+class Q_GUI_EXPORT QPlatformVulkanInstance
{
- using QVarLengthArray<T, Prealloc>::s;
- using QVarLengthArray<T, Prealloc>::a;
- using QVarLengthArray<T, Prealloc>::ptr;
- using QVarLengthArray<T, Prealloc>::realloc;
-public:
- inline explicit QPodList(int size = 0)
- : QVarLengthArray<T, Prealloc>(size)
- {}
+ Q_DECLARE_PRIVATE(QPlatformVulkanInstance)
- inline void insert(int idx, const T &t)
- {
- const int sz = s++;
- if (s == a)
- realloc(s, s << 1);
- ::memmove(ptr + idx + 1, ptr + idx, (sz - idx) * sizeof(T));
- ptr[idx] = t;
- }
-
- inline void removeAll(const T &t)
- {
- int i = 0;
- for (int j = 0; j < s; ++j) {
- if (ptr[j] != t)
- ptr[i++] = ptr[j];
- }
- s = i;
- }
+public:
+ QPlatformVulkanInstance();
+ virtual ~QPlatformVulkanInstance();
- inline void removeAt(int idx)
- {
- Q_ASSERT(idx >= 0 && idx < s);
- ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
- --s;
- }
+ virtual QVulkanInfoVector<QVulkanLayer> supportedLayers() const = 0;
+ virtual QVulkanInfoVector<QVulkanExtension> supportedExtensions() const = 0;
+ virtual void createOrAdoptInstance() = 0;
+ virtual bool isValid() const = 0;
+ virtual VkResult errorCode() const = 0;
+ virtual VkInstance vkInstance() const = 0;
+ virtual QByteArrayList enabledLayers() const = 0;
+ virtual QByteArrayList enabledExtensions() const = 0;
+ virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0;
+ virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0;
+ virtual void presentQueued(QWindow *window);
- inline T takeFirst()
- {
- Q_ASSERT(s > 0);
- T tmp = ptr[0];
- removeAt(0);
- return tmp;
- }
+private:
+ QScopedPointer<QPlatformVulkanInstancePrivate> d_ptr;
+ Q_DISABLE_COPY(QPlatformVulkanInstance)
};
QT_END_NAMESPACE
-#endif // QPODLIST_P_H
+#endif // QT_CONFIG(vulkan)
+
+#endif // QPLATFORMVULKANINSTANCE_H
diff --git a/src/gui/vulkan/qt_attribution.json b/src/gui/vulkan/qt_attribution.json
new file mode 100644
index 0000000000..3c09e9f498
--- /dev/null
+++ b/src/gui/vulkan/qt_attribution.json
@@ -0,0 +1,17 @@
+[
+ {
+ "Id": "vulkan-xml-spec",
+ "Name": "Vulkan API Registry",
+ "QDocModule": "qtgui",
+ "Description": "Vulkan XML API Registry.",
+ "QtUsage": "Used to dynamically generate the sources for the QVulkan(Device)Functions classes.",
+ "Path": "vk.xml",
+
+ "Homepage": "https://www.khronos.org/",
+ "Version": "1.0.39",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "KHRONOS_LICENSE.txt",
+ "Copyright": "Copyright (c) 2015-2017 The Khronos Group Inc."
+ }
+]
diff --git a/src/gui/vulkan/qvulkanfunctions.cpp b/src/gui/vulkan/qvulkanfunctions.cpp
new file mode 100644
index 0000000000..c342535780
--- /dev/null
+++ b/src/gui/vulkan/qvulkanfunctions.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** 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$